@caelo-cms/provisioning 0.10.44 → 0.10.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/adc-impersonation.d.ts +28 -0
  2. package/dist/adc-impersonation.d.ts.map +1 -0
  3. package/dist/adc-impersonation.js +148 -0
  4. package/dist/adc-impersonation.js.map +1 -0
  5. package/dist/checkpoint-secrets.d.ts.map +1 -1
  6. package/dist/checkpoint-secrets.js +2 -1
  7. package/dist/checkpoint-secrets.js.map +1 -1
  8. package/dist/cli.js +202 -33
  9. package/dist/cli.js.map +1 -1
  10. package/dist/compose.d.ts +45 -0
  11. package/dist/compose.d.ts.map +1 -1
  12. package/dist/compose.js +112 -29
  13. package/dist/compose.js.map +1 -1
  14. package/dist/gcloud-retry.d.ts +5 -1
  15. package/dist/gcloud-retry.d.ts.map +1 -1
  16. package/dist/gcloud-retry.js.map +1 -1
  17. package/dist/gcloud.d.ts +2 -1
  18. package/dist/gcloud.d.ts.map +1 -1
  19. package/dist/gcloud.js +11 -13
  20. package/dist/gcloud.js.map +1 -1
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +3 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/infra-contract.d.ts +24 -0
  26. package/dist/infra-contract.d.ts.map +1 -0
  27. package/dist/infra-contract.js +25 -0
  28. package/dist/infra-contract.js.map +1 -0
  29. package/dist/install-state.d.ts +66 -2
  30. package/dist/install-state.d.ts.map +1 -1
  31. package/dist/install-state.js +162 -22
  32. package/dist/install-state.js.map +1 -1
  33. package/dist/lifecycle.d.ts +6 -0
  34. package/dist/lifecycle.d.ts.map +1 -1
  35. package/dist/lifecycle.js +189 -819
  36. package/dist/lifecycle.js.map +1 -1
  37. package/dist/migration-runner.d.ts +3 -0
  38. package/dist/migration-runner.d.ts.map +1 -1
  39. package/dist/migration-runner.js +7 -5
  40. package/dist/migration-runner.js.map +1 -1
  41. package/dist/ops-backend.d.ts +46 -0
  42. package/dist/ops-backend.d.ts.map +1 -0
  43. package/dist/ops-backend.js +370 -0
  44. package/dist/ops-backend.js.map +1 -0
  45. package/dist/provisioner-identity.d.ts +103 -0
  46. package/dist/provisioner-identity.d.ts.map +1 -0
  47. package/dist/provisioner-identity.js +323 -0
  48. package/dist/provisioner-identity.js.map +1 -0
  49. package/dist/regions.d.ts.map +1 -1
  50. package/dist/regions.js +2 -1
  51. package/dist/regions.js.map +1 -1
  52. package/dist/release-contract.d.ts +37 -0
  53. package/dist/release-contract.d.ts.map +1 -0
  54. package/dist/release-contract.js +55 -0
  55. package/dist/release-contract.js.map +1 -0
  56. package/dist/release-manifest.d.ts +140 -0
  57. package/dist/release-manifest.d.ts.map +1 -0
  58. package/dist/release-manifest.js +319 -0
  59. package/dist/release-manifest.js.map +1 -0
  60. package/dist/self-command.d.ts +16 -0
  61. package/dist/self-command.d.ts.map +1 -0
  62. package/dist/self-command.js +20 -0
  63. package/dist/self-command.js.map +1 -0
  64. package/dist/self-hosted-release.d.ts +81 -0
  65. package/dist/self-hosted-release.d.ts.map +1 -0
  66. package/dist/self-hosted-release.js +148 -0
  67. package/dist/self-hosted-release.js.map +1 -0
  68. package/dist/self-hosted-upgrade.d.ts +91 -0
  69. package/dist/self-hosted-upgrade.d.ts.map +1 -0
  70. package/dist/self-hosted-upgrade.js +355 -0
  71. package/dist/self-hosted-upgrade.js.map +1 -0
  72. package/dist/stack-converge.d.ts.map +1 -1
  73. package/dist/stack-converge.js +2 -1
  74. package/dist/stack-converge.js.map +1 -1
  75. package/dist/state-attach.d.ts +23 -0
  76. package/dist/state-attach.d.ts.map +1 -0
  77. package/dist/state-attach.js +112 -0
  78. package/dist/state-attach.js.map +1 -0
  79. package/dist/state-backend.d.ts +114 -0
  80. package/dist/state-backend.d.ts.map +1 -0
  81. package/dist/state-backend.js +200 -0
  82. package/dist/state-backend.js.map +1 -0
  83. package/dist/state-command.d.ts +20 -0
  84. package/dist/state-command.d.ts.map +1 -0
  85. package/dist/state-command.js +237 -0
  86. package/dist/state-command.js.map +1 -0
  87. package/dist/state-migrate.d.ts +121 -0
  88. package/dist/state-migrate.d.ts.map +1 -0
  89. package/dist/state-migrate.js +290 -0
  90. package/dist/state-migrate.js.map +1 -0
  91. package/dist/state-pulumi.d.ts +17 -0
  92. package/dist/state-pulumi.d.ts.map +1 -0
  93. package/dist/state-pulumi.js +218 -0
  94. package/dist/state-pulumi.js.map +1 -0
  95. package/dist/state-store.d.ts +82 -0
  96. package/dist/state-store.d.ts.map +1 -0
  97. package/dist/state-store.js +205 -0
  98. package/dist/state-store.js.map +1 -0
  99. package/dist/upgrade/app-roll.d.ts +164 -0
  100. package/dist/upgrade/app-roll.d.ts.map +1 -0
  101. package/dist/upgrade/app-roll.js +270 -0
  102. package/dist/upgrade/app-roll.js.map +1 -0
  103. package/dist/upgrade/backup.d.ts +48 -0
  104. package/dist/upgrade/backup.d.ts.map +1 -0
  105. package/dist/upgrade/backup.js +71 -0
  106. package/dist/upgrade/backup.js.map +1 -0
  107. package/dist/upgrade/converge.d.ts +45 -0
  108. package/dist/upgrade/converge.d.ts.map +1 -0
  109. package/dist/upgrade/converge.js +287 -0
  110. package/dist/upgrade/converge.js.map +1 -0
  111. package/dist/upgrade/gcp-lookup.d.ts +23 -0
  112. package/dist/upgrade/gcp-lookup.d.ts.map +1 -0
  113. package/dist/upgrade/gcp-lookup.js +95 -0
  114. package/dist/upgrade/gcp-lookup.js.map +1 -0
  115. package/dist/upgrade/health.d.ts +99 -0
  116. package/dist/upgrade/health.d.ts.map +1 -0
  117. package/dist/upgrade/health.js +214 -0
  118. package/dist/upgrade/health.js.map +1 -0
  119. package/dist/upgrade/release-images.d.ts +125 -0
  120. package/dist/upgrade/release-images.d.ts.map +1 -0
  121. package/dist/upgrade/release-images.js +315 -0
  122. package/dist/upgrade/release-images.js.map +1 -0
  123. package/dist/upgrade/reporter.d.ts +17 -0
  124. package/dist/upgrade/reporter.d.ts.map +1 -0
  125. package/dist/upgrade/reporter.js +28 -0
  126. package/dist/upgrade/reporter.js.map +1 -0
  127. package/dist/upgrade/upgrade.d.ts +79 -0
  128. package/dist/upgrade/upgrade.d.ts.map +1 -0
  129. package/dist/upgrade/upgrade.js +105 -0
  130. package/dist/upgrade/upgrade.js.map +1 -0
  131. package/dist/wizard.d.ts.map +1 -1
  132. package/dist/wizard.js +7 -3
  133. package/dist/wizard.js.map +1 -1
  134. package/dist/wizards/gcp-cost.d.ts.map +1 -1
  135. package/dist/wizards/gcp-cost.js +7 -1
  136. package/dist/wizards/gcp-cost.js.map +1 -1
  137. package/dist/wizards/gcp-pulumi.d.ts +104 -8
  138. package/dist/wizards/gcp-pulumi.d.ts.map +1 -1
  139. package/dist/wizards/gcp-pulumi.js +159 -50
  140. package/dist/wizards/gcp-pulumi.js.map +1 -1
  141. package/dist/wizards/gcp.d.ts.map +1 -1
  142. package/dist/wizards/gcp.js +246 -78
  143. package/dist/wizards/gcp.js.map +1 -1
  144. package/package.json +4 -3
  145. package/stacks/self-hosted/README.md +4 -0
  146. package/stacks/self-hosted/index.ts +10 -2
@@ -0,0 +1,287 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * The converge half of an upgrade (epic #696): everything that changes IAM,
4
+ * service accounts, secrets or other cloud resources so the install matches
5
+ * what the release's stacks declare — the gateway's run SA and the
6
+ * CLI-generated runtime secrets, the stack's IAM/CDN/firewall invariants,
7
+ * MCP access through IAP, the gateway's and public_role's database logins,
8
+ * the operator-access sync job, and dropping bindings nothing reads any more.
9
+ *
10
+ * It needs the rights of whoever provisioned the install, so only
11
+ * `cms-provision upgrade` (the operator's own identity) runs it — never the
12
+ * in-cloud upgrader job, which only app-rolls and refuses while
13
+ * {@link needsConverge} says the install is behind.
14
+ *
15
+ * The keyless-provisioner step (#696, provisioner-identity.ts) is converge
16
+ * too; it needs the operator's local install dir, so the CLI injects it as
17
+ * {@link ConvergeDeps.provisionerIdentity}.
18
+ *
19
+ * Some steps must sit between app-roll steps (a role migration 0248 creates
20
+ * gets its password after migrations, before the gateway rolls onto it), so
21
+ * a converge is a {@link ConvergeSession}: a part before the app-roll, the
22
+ * {@link AppRollHooks} the app-roll calls in between, and a part after it.
23
+ */
24
+ import { ensureGatewayRolePassword, findSqlInstance, planPublicRoleSwitch, } from "../gateway-credentials.js";
25
+ import { ensureMcpIapAccess } from "../mcp-iap.js";
26
+ import { ensureOperatorAccessSync, resolveOperatorAccessTarget } from "../operator-access.js";
27
+ import { ensureGatewayServiceAccount, ensureGeneratedSecrets, plainGeneratedSecretSeed, readSecretReplication, } from "../runtime-secrets.js";
28
+ import { selfCommand } from "../self-command.js";
29
+ import { MCP_ENV_VAR, OPERATOR_ACCESS_JOB_ENV_VAR } from "../stack-contract.js";
30
+ import { ensureStackInvariants, liveEnvHasInlinePassword, removeRetiredIamBindings, } from "../stack-converge.js";
31
+ /**
32
+ * Whether the install must converge before an app-roll to a release that
33
+ * expects infrastructure contract `targetVersion` (infra-contract.ts). An
34
+ * install with no recorded version has never completed a converge under
35
+ * this scheme and always needs one.
36
+ */
37
+ export function needsConverge(install, targetVersion) {
38
+ return (install.infraContractVersion ?? 0) < targetVersion;
39
+ }
40
+ /** Start a converge for the install `plan` rolls. */
41
+ export function startConverge(plan, ownerEmail, deps) {
42
+ const { install } = plan;
43
+ const { reporter: r, run } = deps;
44
+ const runDeps = { run, ...(deps.sleep ? { sleep: deps.sleep } : {}) };
45
+ const service = (slug) => plan.services.find((s) => s.slug === slug);
46
+ const services = { admin: service("admin").serviceName, gateway: service("gateway").serviceName };
47
+ const target = {
48
+ provider: install.provider,
49
+ projectId: install.projectId,
50
+ region: install.region,
51
+ env: install.env,
52
+ services,
53
+ };
54
+ let incomplete = false;
55
+ // Env vars the rolls must leave as the services have them, because the
56
+ // thing they point at could not be set up.
57
+ const leaveUntouched = [];
58
+ let publicRole = null;
59
+ async function runtimeIdentities() {
60
+ // The gateway's own run SA and the CLI-generated secrets the env
61
+ // contract references. Created once, never overwritten; must exist
62
+ // before the invariants bind them and the rolls reference them.
63
+ const s = r.step("Ensuring the gateway service account + generated runtime secrets...");
64
+ const secretsTarget = { projectId: install.projectId, env: install.env };
65
+ const replication = await readSecretReplication(secretsTarget, runDeps);
66
+ const outcomes = [
67
+ await ensureGatewayServiceAccount(secretsTarget, runDeps),
68
+ ...(replication.ok
69
+ ? await ensureGeneratedSecrets({
70
+ ...secretsTarget,
71
+ region: install.region,
72
+ replication: replication.replication,
73
+ seed: plainGeneratedSecretSeed(service("admin").liveEnv),
74
+ }, runDeps)
75
+ : [{ id: "secret replication", status: "failed", error: replication.error }]),
76
+ ];
77
+ const failed = outcomes.filter((o) => o.status === "failed");
78
+ if (failed.length > 0) {
79
+ s.failed("Runtime identities/secrets could not be ensured. Aborting upgrade.");
80
+ for (const o of failed)
81
+ r.error(` FAILED: ${o.id}\n ${o.error ?? ""}`);
82
+ r.warn("No traffic was shifted and no migrations ran. Fix the above and re-run.");
83
+ return false;
84
+ }
85
+ s.done("Gateway service account + runtime secrets ok");
86
+ for (const o of outcomes.filter((o) => o.status === "applied")) {
87
+ r.info(` created: ${o.id}${o.detail ? ` (${o.detail})` : ""}`);
88
+ }
89
+ return true;
90
+ }
91
+ async function stackInvariants() {
92
+ // IAM bindings + CDN policy added to the stacks after this install was
93
+ // provisioned (stack-contract.ts), and GCP's SSH/RDP-from-anywhere
94
+ // firewall rules removed (default-firewall.ts). Additive + idempotent.
95
+ const s = r.step("Ensuring the IAM bindings + CDN settings the stack declares, removing the default network's pre-populated firewall rules...");
96
+ const report = await ensureStackInvariants(target, runDeps);
97
+ const applied = report.outcomes.filter((o) => o.status === "applied");
98
+ const failed = report.outcomes.filter((o) => o.status === "failed");
99
+ if (report.mustAbort)
100
+ s.failed("Stack invariants could not be ensured. Aborting upgrade.");
101
+ else {
102
+ s.done(`Stack invariants ok (${report.outcomes.length - failed.length}/${report.outcomes.length}, ${applied.length} applied)`);
103
+ }
104
+ for (const o of applied)
105
+ r.info(` applied: ${o.id} (${o.why})`);
106
+ for (const o of failed) {
107
+ const line = ` ${o.onFailure === "abort" ? "FAILED" : "not applied"}: ${o.id} — ${o.why}\n ${o.error ?? ""}`;
108
+ if (o.onFailure === "abort")
109
+ r.error(line);
110
+ else
111
+ r.warn(line);
112
+ }
113
+ if (failed.length > 0)
114
+ incomplete = true;
115
+ if (report.mustAbort) {
116
+ r.warn("No traffic was shifted and no migrations ran. Fix the bindings above and re-run.");
117
+ return false;
118
+ }
119
+ return true;
120
+ }
121
+ async function mcpAccess() {
122
+ // Issue #37 — the MCP service account + its IAP/token-creator bindings.
123
+ // Also what the deep health check signs its IAP credential as. A failure
124
+ // costs MCP access, so it warns and the admin keeps its current value.
125
+ const s = r.step("Ensuring MCP access through IAP...");
126
+ // Signing as the MCP account goes through the IAM Credentials API, which
127
+ // installs from before #678 may not have enabled.
128
+ const api = await run([
129
+ "services",
130
+ "enable",
131
+ "iamcredentials.googleapis.com",
132
+ `--project=${install.projectId}`,
133
+ ]);
134
+ const resource = api.ok ? await adminIapResource() : null;
135
+ const mcp = !api.ok
136
+ ? {
137
+ ok: false,
138
+ error: `enable the IAM Credentials API (iamcredentials.googleapis.com): ${api.stderr.trim()}`,
139
+ }
140
+ : resource
141
+ ? await ensureMcpIapAccess({ projectId: install.projectId, resource, ...runDeps })
142
+ : { ok: false, error: "admin IAP backend service not found" };
143
+ if (mcp.ok) {
144
+ s.done(`MCP access ready (${mcp.serviceAccount}; ${mcp.operators.length} operator(s))`);
145
+ return;
146
+ }
147
+ s.warned(`MCP access not configured: ${mcp.error}`);
148
+ r.warn("The upgrade continues; external MCP clients stay blocked by IAP until this succeeds.");
149
+ incomplete = true;
150
+ leaveUntouched.push(MCP_ENV_VAR);
151
+ }
152
+ /** The admin's IAP resource: the service on gcp-firebase, the LB backend on gcp. */
153
+ async function adminIapResource() {
154
+ if (install.provider === "gcp-firebase") {
155
+ return { kind: "cloud-run", service: services.admin, region: install.region };
156
+ }
157
+ const res = await run([
158
+ "compute",
159
+ "backend-services",
160
+ "list",
161
+ "--global",
162
+ `--project=${install.projectId}`,
163
+ `--filter=name~^caelo-${install.env}-admin-backend`,
164
+ "--format=value(name)",
165
+ ]);
166
+ const name = res.ok ? res.stdout.trim().split("\n")[0]?.trim() : "";
167
+ return name ? { kind: "backend-services", service: name } : null;
168
+ }
169
+ async function databaseLogins() {
170
+ // #613 — migration 0248 creates gateway_role without a password; it gets
171
+ // its secret's value before the gateway rolls onto it. public_role
172
+ // moves onto its own password right before the gateway's roll.
173
+ const s = r.step("Ensuring the gateway's database login (gateway_role)...");
174
+ const sqlInstance = await findSqlInstance(install, { run });
175
+ if (!sqlInstance) {
176
+ s.failed("Could not find the Cloud SQL instance. Aborting upgrade.");
177
+ r.warn("Migrations ran; no traffic was shifted. Re-run upgrade once the instance is found.");
178
+ return false;
179
+ }
180
+ const roleTarget = { projectId: install.projectId, env: install.env, sqlInstance };
181
+ const roleDeps = { ...runDeps, ...(deps.http ? { http: deps.http } : {}) };
182
+ const gatewayRole = await ensureGatewayRolePassword(roleTarget, roleDeps);
183
+ if (gatewayRole.status === "failed") {
184
+ s.failed("gateway_role could not be given its password. Aborting upgrade.");
185
+ r.error(` ${gatewayRole.error ?? ""}`);
186
+ r.warn("Migrations ran (0248 creates gateway_role); no traffic was shifted. Fix the above and re-run upgrade.");
187
+ return false;
188
+ }
189
+ s.done("gateway_role ready");
190
+ publicRole = planPublicRoleSwitch(roleTarget, service("gateway").liveEnv, roleDeps);
191
+ return true;
192
+ }
193
+ async function operatorAccess() {
194
+ // The job that keeps IAP in step with the user list (operator-access.ts).
195
+ // After migrations: its database user gets the role migration 0239
196
+ // creates. A failure only costs IAP following the user list, so it warns.
197
+ const s = r.step("Ensuring the operator-access sync job...");
198
+ const resolved = await resolveOperatorAccessTarget({
199
+ provider: install.provider,
200
+ projectId: install.projectId,
201
+ region: install.region,
202
+ env: install.env,
203
+ ownerEmail,
204
+ imageRef: service("admin").imageRef,
205
+ }, { run });
206
+ const oa = resolved.ok
207
+ ? await ensureOperatorAccessSync(resolved.target, runDeps)
208
+ : { ok: false, done: [], error: resolved.error };
209
+ for (const step of oa.done)
210
+ r.info(` ${step}`);
211
+ if (oa.ok) {
212
+ s.done("Operator-access sync job ready (IAP follows the user list)");
213
+ return;
214
+ }
215
+ s.warned(`Operator-access sync job not set up: ${oa.error}`);
216
+ r.warn("The upgrade continues; user changes will report that Google IAP could not be updated until this succeeds. Re-run upgrade once the cause is fixed.");
217
+ incomplete = true;
218
+ leaveUntouched.push(OPERATOR_ACCESS_JOB_ENV_VAR);
219
+ }
220
+ return {
221
+ async beforeAppRoll() {
222
+ if (deps.provisionerIdentity && !(await deps.provisionerIdentity()))
223
+ return false;
224
+ if (!(await runtimeIdentities()))
225
+ return false;
226
+ if (!(await stackInvariants()))
227
+ return false;
228
+ await mcpAccess();
229
+ return true;
230
+ },
231
+ hooks: {
232
+ async afterMigrations() {
233
+ if (!(await databaseLogins()))
234
+ return { ok: false };
235
+ await operatorAccess();
236
+ return { ok: true, leaveUntouched: [...leaveUntouched] };
237
+ },
238
+ async beforeRoll(slug) {
239
+ if (slug !== "gateway" || !publicRole)
240
+ return { ok: true };
241
+ const moved = await publicRole.beforeGatewayRoll();
242
+ return moved.status === "failed"
243
+ ? {
244
+ ok: false,
245
+ error: `public_role could not be moved onto its own password: ${moved.error ?? ""}`,
246
+ }
247
+ : { ok: true };
248
+ },
249
+ async afterRollback(slug) {
250
+ // The prior gateway revision reads public_role's old password.
251
+ if (slug !== "gateway" || !publicRole)
252
+ return;
253
+ const outcome = await publicRole.afterGatewayRollFailed();
254
+ if (outcome.startsWith("could NOT"))
255
+ r.error(` ${outcome}`);
256
+ else
257
+ r.info(` ${outcome}`);
258
+ },
259
+ },
260
+ async afterAppRoll() {
261
+ // #613 — with both services on their new revisions, drop the bindings
262
+ // nothing reads through any more (above all the gateway SA's access to
263
+ // admin_role's password). Loud on failure.
264
+ const retired = await removeRetiredIamBindings(target, runDeps);
265
+ for (const o of retired) {
266
+ if (o.status === "removed")
267
+ r.info(` removed: ${o.id} (${o.why})`);
268
+ if (o.status === "failed") {
269
+ incomplete = true;
270
+ r.error(` NOT removed: ${o.id} — ${o.why}\n ${o.error ?? ""}\n Re-run upgrade with an account that may change IAM, or remove the binding by hand.`);
271
+ }
272
+ }
273
+ if (publicRole?.moves) {
274
+ // Until this upgrade the gateway held admin_role's password; anyone
275
+ // who ever compromised it could have kept a copy.
276
+ r.warn(`The gateway no longer holds admin_role's password, but it did until now. Rotate it: ${selfCommand("rotate-secret", "postgres-password", "--install", install.domain)}`);
277
+ }
278
+ if (plan.services.some((s) => liveEnvHasInlinePassword(s.liveEnv))) {
279
+ // The services moved their database password to Secret Manager, but
280
+ // every earlier revision still shows it in its env.
281
+ r.warn(`The database password was stored in plain env vars before this upgrade and stays readable in the services' old revisions. Rotate it now: ${selfCommand("rotate-secret", "postgres-password", "--install", install.domain)}`);
282
+ }
283
+ },
284
+ complete: () => !incomplete,
285
+ };
286
+ }
287
+ //# sourceMappingURL=converge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converge.js","sourceRoot":"","sources":["../../src/upgrade/converge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Read-only lookups of a deployed GCP install, plus the one traffic move an
3
+ * app-roll needs to undo itself. Every function takes the {@link GcloudRunner}
4
+ * it runs through, so the upgrade phases can be driven by a fake in tests and
5
+ * by a different identity in the in-cloud upgrader job (epic #696).
6
+ */
7
+ import type { GcloudRunner } from "../gcloud-retry.js";
8
+ /**
9
+ * Pulumi auto-naming appends a random 7-char suffix to every resource
10
+ * (e.g. `caelo-production-admin-3efcfea`), so lifecycle commands find the
11
+ * deployed name by prefix. Returns the first match, or null when the listing
12
+ * fails or finds nothing.
13
+ */
14
+ export declare function resolveGcpResourceName(run: GcloudRunner, kind: "run-service" | "sql-instance", prefix: string, projectId: string, region?: string): Promise<string | null>;
15
+ /** The deployed service as `gcloud run services describe --format=json` returns it. */
16
+ export declare function describeServiceJson(run: GcloudRunner, projectId: string, region: string, serviceName: string): Promise<string | null>;
17
+ /** The revision serving traffic now, so a failed roll can go back to it. */
18
+ export declare function findCurrentRevision(run: GcloudRunner, projectId: string, region: string, serviceName: string): Promise<string | null>;
19
+ /** The service's own `run.app` URL. */
20
+ export declare function findServiceUrl(run: GcloudRunner, projectId: string, region: string, serviceName: string): Promise<string | null>;
21
+ /** Pin all of a service's traffic to `revision`. */
22
+ export declare function pinTraffic(run: GcloudRunner, projectId: string, region: string, serviceName: string, revision: string): Promise<boolean>;
23
+ //# sourceMappingURL=gcp-lookup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-lookup.d.ts","sourceRoot":"","sources":["../../src/upgrade/gcp-lookup.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAAG,cAAc,EACpC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AAsBD,uFAAuF;AACvF,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAED,4EAA4E;AAC5E,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMxB;AAED,uCAAuC;AACvC,wBAAsB,cAAc,CAClC,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAED,oDAAoD;AACpD,wBAAsB,UAAU,CAC9B,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAelB"}
@@ -0,0 +1,95 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * Pulumi auto-naming appends a random 7-char suffix to every resource
4
+ * (e.g. `caelo-production-admin-3efcfea`), so lifecycle commands find the
5
+ * deployed name by prefix. Returns the first match, or null when the listing
6
+ * fails or finds nothing.
7
+ */
8
+ export async function resolveGcpResourceName(run, kind, prefix, projectId, region) {
9
+ const args = kind === "run-service"
10
+ ? [
11
+ "run",
12
+ "services",
13
+ "list",
14
+ "--region",
15
+ requiredRegion(region),
16
+ "--project",
17
+ projectId,
18
+ "--filter",
19
+ `metadata.name~^${prefix}`,
20
+ "--format=value(metadata.name)",
21
+ ]
22
+ : [
23
+ "sql",
24
+ "instances",
25
+ "list",
26
+ "--project",
27
+ projectId,
28
+ "--filter",
29
+ `name~^${prefix}`,
30
+ "--format=value(name)",
31
+ ];
32
+ const r = await run(args);
33
+ if (!r.ok)
34
+ return null;
35
+ return (r.stdout
36
+ .split("\n")
37
+ .map((s) => s.trim())
38
+ .find((s) => s.length > 0) ?? null);
39
+ }
40
+ /** A Cloud Run lookup is regional; there is no default region to guess. */
41
+ function requiredRegion(region) {
42
+ if (!region)
43
+ throw new Error("a Cloud Run lookup needs the install region (install.json)");
44
+ return region;
45
+ }
46
+ function describeArgs(serviceName, region, projectId, format) {
47
+ return [
48
+ "run",
49
+ "services",
50
+ "describe",
51
+ serviceName,
52
+ "--region",
53
+ region,
54
+ "--project",
55
+ projectId,
56
+ `--format=${format}`,
57
+ ];
58
+ }
59
+ /** The deployed service as `gcloud run services describe --format=json` returns it. */
60
+ export async function describeServiceJson(run, projectId, region, serviceName) {
61
+ const r = await run(describeArgs(serviceName, region, projectId, "json"));
62
+ return r.ok ? r.stdout : null;
63
+ }
64
+ /** The revision serving traffic now, so a failed roll can go back to it. */
65
+ export async function findCurrentRevision(run, projectId, region, serviceName) {
66
+ const r = await run(describeArgs(serviceName, region, projectId, "value(status.traffic[0].revisionName)"));
67
+ if (!r.ok)
68
+ return null;
69
+ return r.stdout.trim().split("\n")[0]?.trim() || null;
70
+ }
71
+ /** The service's own `run.app` URL. */
72
+ export async function findServiceUrl(run, projectId, region, serviceName) {
73
+ const r = await run(describeArgs(serviceName, region, projectId, "value(status.url)"));
74
+ if (!r.ok)
75
+ return null;
76
+ return r.stdout.trim() || null;
77
+ }
78
+ /** Pin all of a service's traffic to `revision`. */
79
+ export async function pinTraffic(run, projectId, region, serviceName, revision) {
80
+ const r = await run([
81
+ "run",
82
+ "services",
83
+ "update-traffic",
84
+ serviceName,
85
+ "--region",
86
+ region,
87
+ "--project",
88
+ projectId,
89
+ "--to-revisions",
90
+ `${revision}=100`,
91
+ "--quiet",
92
+ ]);
93
+ return r.ok;
94
+ }
95
+ //# sourceMappingURL=gcp-lookup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-lookup.js","sourceRoot":"","sources":["../../src/upgrade/gcp-lookup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Deep health check after an app-roll (epic #696).
3
+ *
4
+ * Cloud Run's readiness only proves the new container listens on its port. A
5
+ * revision can do that while it cannot reach the database, runs against a
6
+ * schema its migrations never reached, or is not the release the roll asked
7
+ * for. After both services moved, the app-roll asks them:
8
+ *
9
+ * - admin `GET /_caelo/health?deep=1` → `{ ok, version, migrations }`:
10
+ * both databases reachable as the expected roles, and every
11
+ * migration the image ships recorded as applied.
12
+ * - gateway `GET /api/_caelo/health?deep=1` → `{ ok, version }`: its
13
+ * database logins work. Under `/api/` because that is the only
14
+ * path the gcp load balancer routes to the gateway.
15
+ *
16
+ * Both answer with no secrets and no raw database errors. The admin sits
17
+ * behind IAP, so the probe signs an IAP credential as the install's MCP
18
+ * service account (`caelo-mcp@`, mcp-iap.ts) exactly like the MCP shim does
19
+ * (packages/mcp-server/src/ingress-auth.ts): a JWT with `aud` = the admin
20
+ * origin + `/*`, signed through the IAM Credentials API by whoever runs the
21
+ * upgrade (the converge step lets every IAP-allowlisted operator sign as
22
+ * that account). The gateway is public by design and gets no credential.
23
+ *
24
+ * Before anything changes, {@link HealthProbe.baseline} proves the probe can
25
+ * reach both services at all. Otherwise a DNS, certificate or IAP problem
26
+ * would only show after migrations, as a "failed" health check that rolls a
27
+ * healthy release back.
28
+ */
29
+ import type { GcloudRunner, Sleep } from "../gcloud-retry.js";
30
+ import type { HttpFetch } from "../runtime-secrets.js";
31
+ export type HealthOutcome = {
32
+ readonly ok: true;
33
+ readonly detail: string;
34
+ } | {
35
+ readonly ok: false;
36
+ readonly error: string;
37
+ };
38
+ export interface HealthProbe {
39
+ /** Reach both services as they serve now (before any change). */
40
+ baseline(): Promise<HealthOutcome>;
41
+ /**
42
+ * Deep-check both services after the roll, retrying while the new
43
+ * revisions warm up. `version` is the release the roll targets (null when
44
+ * a channel tag like `latest` was rolled: then both must report the same
45
+ * version).
46
+ */
47
+ deep(expect: {
48
+ readonly version: string | null;
49
+ }): Promise<HealthOutcome>;
50
+ }
51
+ /**
52
+ * Judge the admin's deep health answer.
53
+ *
54
+ * @returns the version the admin runs on success
55
+ */
56
+ export declare function evaluateAdminDeepHealth(status: number, text: string, expectedVersion: string | null): {
57
+ ok: true;
58
+ version: string;
59
+ detail: string;
60
+ } | {
61
+ ok: false;
62
+ error: string;
63
+ };
64
+ /** Judge the gateway's deep health answer against the version the admin runs. */
65
+ export declare function evaluateGatewayDeepHealth(status: number, text: string, expectedVersion: string): HealthOutcome;
66
+ /** Where the probe reaches the install. */
67
+ export interface HealthTarget {
68
+ readonly provider: "gcp" | "gcp-firebase";
69
+ readonly projectId: string;
70
+ readonly domain: string;
71
+ /** The admin service's `run.app` URL (IAP-gated on gcp-firebase). */
72
+ readonly adminServiceUrl: string;
73
+ /** The gateway service's `run.app` URL (public on gcp-firebase). */
74
+ readonly gatewayServiceUrl: string;
75
+ }
76
+ /**
77
+ * The origins the probe calls. On gcp the admin's IAP lives on the load
78
+ * balancer (`admin.<domain>`) and the gateway's ingress is load-balancer-only
79
+ * (`<domain>/api/*`); on gcp-firebase both `run.app` URLs are reachable — the
80
+ * admin's through Cloud Run's own IAP, the gateway's publicly.
81
+ */
82
+ export declare function healthOrigins(target: HealthTarget): {
83
+ admin: string;
84
+ gateway: string;
85
+ };
86
+ export interface HealthProbeDeps {
87
+ readonly run: GcloudRunner;
88
+ readonly http: HttpFetch;
89
+ readonly sleep: Sleep;
90
+ /** Deep-check attempts while the new revisions warm up (default 12). */
91
+ readonly attempts?: number;
92
+ /** Pause between attempts in ms (default 5000). */
93
+ readonly intervalMs?: number;
94
+ /** Seconds since epoch. */
95
+ readonly now?: () => number;
96
+ }
97
+ /** The IAP-backed probe of a gcp / gcp-firebase install. */
98
+ export declare function createIapHealthProbe(target: HealthTarget, deps: HealthProbeDeps): HealthProbe;
99
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/upgrade/health.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,QAAQ,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IACnC;;;;;OAKG;IACH,IAAI,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC3E;AAuBD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,MAAM,GAAG,IAAI,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAuC9E;AAED,iFAAiF;AACjF,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,MAAM,GACtB,aAAa,CAgBf;AAED,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,KAAK,GAAG,cAAc,CAAC;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,oEAAoE;IACpE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAOtF;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,2BAA2B;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAKD,4DAA4D;AAC5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,GAAG,WAAW,CAqH7F"}