@caelo-cms/provisioning 0.10.47 → 0.10.49
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.
- package/caddy/Caddyfile.production +1 -1
- package/caddy/Caddyfile.staging +1 -1
- package/dist/agent/apply.d.ts +45 -0
- package/dist/agent/apply.d.ts.map +1 -0
- package/dist/agent/apply.js +83 -0
- package/dist/agent/apply.js.map +1 -0
- package/dist/agent/cli-provenance.d.ts +42 -0
- package/dist/agent/cli-provenance.d.ts.map +1 -0
- package/dist/agent/cli-provenance.js +138 -0
- package/dist/agent/cli-provenance.js.map +1 -0
- package/dist/agent/command.d.ts +79 -0
- package/dist/agent/command.d.ts.map +1 -0
- package/dist/agent/command.js +454 -0
- package/dist/agent/command.js.map +1 -0
- package/dist/agent/config.d.ts +30 -0
- package/dist/agent/config.d.ts.map +1 -0
- package/dist/agent/config.js +60 -0
- package/dist/agent/config.js.map +1 -0
- package/dist/agent/lock.d.ts +13 -0
- package/dist/agent/lock.d.ts.map +1 -0
- package/dist/agent/lock.js +100 -0
- package/dist/agent/lock.js.map +1 -0
- package/dist/agent/queue.d.ts +35 -0
- package/dist/agent/queue.d.ts.map +1 -0
- package/dist/agent/queue.js +50 -0
- package/dist/agent/queue.js.map +1 -0
- package/dist/agent/run.d.ts +97 -0
- package/dist/agent/run.d.ts.map +1 -0
- package/dist/agent/run.js +198 -0
- package/dist/agent/run.js.map +1 -0
- package/dist/agent/systemd.d.ts +55 -0
- package/dist/agent/systemd.d.ts.map +1 -0
- package/dist/agent/systemd.js +171 -0
- package/dist/agent/systemd.js.map +1 -0
- package/dist/agent/units.d.ts +44 -0
- package/dist/agent/units.d.ts.map +1 -0
- package/dist/agent/units.js +127 -0
- package/dist/agent/units.js.map +1 -0
- package/dist/agent-db.js +18402 -0
- package/dist/cli.js +119 -16
- package/dist/cli.js.map +1 -1
- package/dist/cloudsql-iam-user.d.ts +39 -0
- package/dist/cloudsql-iam-user.d.ts.map +1 -0
- package/dist/cloudsql-iam-user.js +119 -0
- package/dist/cloudsql-iam-user.js.map +1 -0
- package/dist/compose.d.ts +16 -0
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +26 -1
- package/dist/compose.js.map +1 -1
- package/dist/dns/index.d.ts +2 -0
- package/dist/dns/index.d.ts.map +1 -1
- package/dist/dns/index.js +3 -2
- package/dist/dns/index.js.map +1 -1
- package/dist/dns/manual.d.ts +5 -0
- package/dist/dns/manual.d.ts.map +1 -1
- package/dist/dns/manual.js +28 -12
- package/dist/dns/manual.js.map +1 -1
- package/dist/gcloud.d.ts +2 -0
- package/dist/gcloud.d.ts.map +1 -1
- package/dist/gcloud.js +1 -1
- package/dist/gcloud.js.map +1 -1
- package/dist/gcp-names.d.ts +15 -0
- package/dist/gcp-names.d.ts.map +1 -1
- package/dist/gcp-names.js +23 -0
- package/dist/gcp-names.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/infra-contract.d.ts +1 -1
- package/dist/infra-contract.js +7 -1
- package/dist/infra-contract.js.map +1 -1
- package/dist/install-job-runner.d.ts +13 -0
- package/dist/install-job-runner.d.ts.map +1 -0
- package/dist/install-job-runner.js +155 -0
- package/dist/install-job-runner.js.map +1 -0
- package/dist/install-job.d.ts +210 -0
- package/dist/install-job.d.ts.map +1 -0
- package/dist/install-job.js +449 -0
- package/dist/install-job.js.map +1 -0
- package/dist/install-state.d.ts +10 -1
- package/dist/install-state.d.ts.map +1 -1
- package/dist/install-state.js +10 -2
- package/dist/install-state.js.map +1 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +19 -4
- package/dist/lifecycle.js.map +1 -1
- package/dist/migration-runner.d.ts +5 -0
- package/dist/migration-runner.d.ts.map +1 -1
- package/dist/migration-runner.js +1 -1
- package/dist/migration-runner.js.map +1 -1
- package/dist/operator-access.d.ts +14 -8
- package/dist/operator-access.d.ts.map +1 -1
- package/dist/operator-access.js +16 -102
- package/dist/operator-access.js.map +1 -1
- package/dist/release-manifest.d.ts +2 -41
- package/dist/release-manifest.d.ts.map +1 -1
- package/dist/release-manifest.js +18 -121
- package/dist/release-manifest.js.map +1 -1
- package/dist/run-mode.d.ts +27 -0
- package/dist/run-mode.d.ts.map +1 -0
- package/dist/run-mode.js +22 -0
- package/dist/run-mode.js.map +1 -0
- package/dist/runtime-secrets.d.ts +19 -0
- package/dist/runtime-secrets.d.ts.map +1 -1
- package/dist/runtime-secrets.js +44 -0
- package/dist/runtime-secrets.js.map +1 -1
- package/dist/self-hosted-roles.d.ts +22 -1
- package/dist/self-hosted-roles.d.ts.map +1 -1
- package/dist/self-hosted-roles.js +81 -12
- package/dist/self-hosted-roles.js.map +1 -1
- package/dist/self-hosted-upgrade.d.ts +17 -0
- package/dist/self-hosted-upgrade.d.ts.map +1 -1
- package/dist/self-hosted-upgrade.js +16 -1
- package/dist/self-hosted-upgrade.js.map +1 -1
- package/dist/stack-contract.d.ts +6 -0
- package/dist/stack-contract.d.ts.map +1 -1
- package/dist/stack-contract.js +10 -1
- package/dist/stack-contract.js.map +1 -1
- package/dist/upgrade/converge.d.ts +6 -0
- package/dist/upgrade/converge.d.ts.map +1 -1
- package/dist/upgrade/converge.js +59 -2
- package/dist/upgrade/converge.js.map +1 -1
- package/dist/upgrade/gcp-lookup.d.ts +6 -0
- package/dist/upgrade/gcp-lookup.d.ts.map +1 -1
- package/dist/upgrade/gcp-lookup.js +25 -0
- package/dist/upgrade/gcp-lookup.js.map +1 -1
- package/dist/upgrade/release-images.d.ts +26 -2
- package/dist/upgrade/release-images.d.ts.map +1 -1
- package/dist/upgrade/release-images.js +35 -2
- package/dist/upgrade/release-images.js.map +1 -1
- package/dist/upgrade/upgrade.d.ts +5 -0
- package/dist/upgrade/upgrade.d.ts.map +1 -1
- package/dist/upgrade/upgrade.js +28 -1
- package/dist/upgrade/upgrade.js.map +1 -1
- package/dist/upgrader-assess.d.ts +85 -0
- package/dist/upgrader-assess.d.ts.map +1 -0
- package/dist/upgrader-assess.js +122 -0
- package/dist/upgrader-assess.js.map +1 -0
- package/dist/upgrader-gcp.d.ts +17 -0
- package/dist/upgrader-gcp.d.ts.map +1 -0
- package/dist/upgrader-gcp.js +87 -0
- package/dist/upgrader-gcp.js.map +1 -0
- package/dist/upgrader-job.d.ts +133 -0
- package/dist/upgrader-job.d.ts.map +1 -0
- package/dist/upgrader-job.js +259 -0
- package/dist/upgrader-job.js.map +1 -0
- package/dist/upgrader-reporter.d.ts +35 -0
- package/dist/upgrader-reporter.d.ts.map +1 -0
- package/dist/upgrader-reporter.js +79 -0
- package/dist/upgrader-reporter.js.map +1 -0
- package/dist/upgrader-setup.d.ts +59 -0
- package/dist/upgrader-setup.d.ts.map +1 -0
- package/dist/upgrader-setup.js +308 -0
- package/dist/upgrader-setup.js.map +1 -0
- package/dist/wizard.d.ts +6 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +32 -4
- package/dist/wizard.js.map +1 -1
- package/dist/wizards/gcp-firebase.d.ts +3 -0
- package/dist/wizards/gcp-firebase.d.ts.map +1 -1
- package/dist/wizards/gcp-firebase.js +1 -0
- package/dist/wizards/gcp-firebase.js.map +1 -1
- package/dist/wizards/gcp-install-job.d.ts +74 -0
- package/dist/wizards/gcp-install-job.d.ts.map +1 -0
- package/dist/wizards/gcp-install-job.js +398 -0
- package/dist/wizards/gcp-install-job.js.map +1 -0
- package/dist/wizards/gcp-prompts.d.ts +3 -0
- package/dist/wizards/gcp-prompts.d.ts.map +1 -0
- package/dist/wizards/gcp-prompts.js +25 -0
- package/dist/wizards/gcp-prompts.js.map +1 -0
- package/dist/wizards/gcp-pulumi.d.ts +4 -2
- package/dist/wizards/gcp-pulumi.d.ts.map +1 -1
- package/dist/wizards/gcp-pulumi.js +1 -1
- package/dist/wizards/gcp-pulumi.js.map +1 -1
- package/dist/wizards/gcp.d.ts +40 -0
- package/dist/wizards/gcp.d.ts.map +1 -1
- package/dist/wizards/gcp.js +223 -59
- package/dist/wizards/gcp.js.map +1 -1
- package/package.json +6 -4
- package/src/adapter.ts +97 -0
- package/src/adc-impersonation.ts +176 -0
- package/src/admin-domain.test.ts +254 -0
- package/src/admin-domain.ts +245 -0
- package/src/admin-memory.test.ts +151 -0
- package/src/agent/apply.test.ts +185 -0
- package/src/agent/apply.ts +124 -0
- package/src/agent/cli-provenance.test.ts +159 -0
- package/src/agent/cli-provenance.ts +191 -0
- package/src/agent/command.test.ts +77 -0
- package/src/agent/command.ts +564 -0
- package/src/agent/config.ts +86 -0
- package/src/agent/lock-config.test.ts +97 -0
- package/src/agent/lock.ts +110 -0
- package/src/agent/queue.test.ts +10 -0
- package/src/agent/queue.ts +91 -0
- package/src/agent/run.test.ts +437 -0
- package/src/agent/run.ts +295 -0
- package/src/agent/systemd.ts +209 -0
- package/src/agent/units.test.ts +223 -0
- package/src/agent/units.ts +163 -0
- package/src/azure-front-door.test.ts +119 -0
- package/src/azure-front-door.ts +56 -0
- package/src/bootstrap-token.ts +20 -0
- package/src/caddy.ts +112 -0
- package/src/cdn-copy.ts +91 -0
- package/src/cert-wait.test.ts +194 -0
- package/src/cert-wait.ts +163 -0
- package/src/checkpoint-secrets.test.ts +380 -0
- package/src/checkpoint-secrets.ts +283 -0
- package/src/cli-routing.test.ts +45 -0
- package/src/cli-routing.ts +43 -0
- package/src/cli.ts +1491 -0
- package/src/cloudsql-iam-user.ts +147 -0
- package/src/compose.ts +334 -0
- package/src/default-firewall.test.ts +411 -0
- package/src/default-firewall.ts +342 -0
- package/src/deployed-release.test.ts +231 -0
- package/src/deployed-release.ts +220 -0
- package/src/dns/cloudflare.ts +182 -0
- package/src/dns/groups.test.ts +76 -0
- package/src/dns/groups.ts +86 -0
- package/src/dns/index.ts +56 -0
- package/src/dns/manual.ts +130 -0
- package/src/dns/types.ts +27 -0
- package/src/gateway-credentials.test.ts +180 -0
- package/src/gateway-credentials.ts +144 -0
- package/src/gcloud-components.test.ts +76 -0
- package/src/gcloud-components.ts +85 -0
- package/src/gcloud-retry.ts +41 -0
- package/src/gcloud-runner.test.ts +61 -0
- package/src/gcloud.test.ts +99 -0
- package/src/gcloud.ts +322 -0
- package/src/gcp-names.ts +135 -0
- package/src/index.test.ts +332 -0
- package/src/index.ts +114 -0
- package/src/infra-contract.ts +32 -0
- package/src/install-job-runner.ts +166 -0
- package/src/install-job.test.ts +566 -0
- package/src/install-job.ts +542 -0
- package/src/install-state.test.ts +239 -0
- package/src/install-state.ts +583 -0
- package/src/internal-token.ts +35 -0
- package/src/lifecycle.ts +900 -0
- package/src/mcp-iap-stacks.test.ts +58 -0
- package/src/mcp-iap.test.ts +149 -0
- package/src/mcp-iap.ts +131 -0
- package/src/media-volume.test.ts +296 -0
- package/src/migration-runner.ts +365 -0
- package/src/operator-access-stacks.test.ts +55 -0
- package/src/operator-access.test.ts +332 -0
- package/src/operator-access.ts +554 -0
- package/src/ops-backend.test.ts +320 -0
- package/src/ops-backend.ts +414 -0
- package/src/provisioner-identity.test.ts +482 -0
- package/src/provisioner-identity.ts +407 -0
- package/src/redirects-emit.ts +175 -0
- package/src/region-data.ts +428 -0
- package/src/regions.test.ts +277 -0
- package/src/regions.ts +370 -0
- package/src/release-contract.ts +57 -0
- package/src/release-manifest.test.ts +300 -0
- package/src/release-manifest.ts +310 -0
- package/src/run-mode.ts +40 -0
- package/src/runtime-secrets.test.ts +627 -0
- package/src/runtime-secrets.ts +754 -0
- package/src/self-command.test.ts +14 -0
- package/src/self-command.ts +21 -0
- package/src/self-hosted-compose.test.ts +177 -0
- package/src/self-hosted-release.ts +240 -0
- package/src/self-hosted-roles.integration.test.ts +161 -0
- package/src/self-hosted-roles.test.ts +124 -0
- package/src/self-hosted-roles.ts +203 -0
- package/src/self-hosted-upgrade.test.ts +394 -0
- package/src/self-hosted-upgrade.ts +548 -0
- package/src/stack-contract-parity.test.ts +199 -0
- package/src/stack-contract.test.ts +391 -0
- package/src/stack-contract.ts +888 -0
- package/src/stack-converge-secrets.test.ts +421 -0
- package/src/stack-converge.test.ts +833 -0
- package/src/stack-converge.ts +909 -0
- package/src/staging-admin.test.ts +246 -0
- package/src/staging-admin.ts +324 -0
- package/src/state-attach.test.ts +211 -0
- package/src/state-attach.ts +132 -0
- package/src/state-backend.test.ts +145 -0
- package/src/state-backend.ts +262 -0
- package/src/state-command.ts +293 -0
- package/src/state-migrate.test.ts +479 -0
- package/src/state-migrate.ts +434 -0
- package/src/state-pulumi.ts +289 -0
- package/src/state-store.test.ts +212 -0
- package/src/state-store.ts +243 -0
- package/src/upgrade/app-roll.ts +486 -0
- package/src/upgrade/backup.ts +109 -0
- package/src/upgrade/converge.ts +437 -0
- package/src/upgrade/gcp-lookup.ts +167 -0
- package/src/upgrade/health.test.ts +279 -0
- package/src/upgrade/health.ts +305 -0
- package/src/upgrade/release-images.test.ts +119 -0
- package/src/upgrade/release-images.ts +393 -0
- package/src/upgrade/reporter.ts +46 -0
- package/src/upgrade/upgrade.test.ts +626 -0
- package/src/upgrade/upgrade.ts +249 -0
- package/src/upgrader-assess.test.ts +306 -0
- package/src/upgrader-assess.ts +250 -0
- package/src/upgrader-gcp.ts +123 -0
- package/src/upgrader-job.test.ts +411 -0
- package/src/upgrader-job.ts +502 -0
- package/src/upgrader-reporter.test.ts +46 -0
- package/src/upgrader-reporter.ts +105 -0
- package/src/upgrader-setup.test.ts +169 -0
- package/src/upgrader-setup.ts +355 -0
- package/src/wizard.ts +425 -0
- package/src/wizards/gcp-cost.ts +188 -0
- package/src/wizards/gcp-firebase.ts +72 -0
- package/src/wizards/gcp-install-job.ts +506 -0
- package/src/wizards/gcp-prompts.ts +26 -0
- package/src/wizards/gcp-pulumi.test.ts +246 -0
- package/src/wizards/gcp-pulumi.ts +516 -0
- package/src/wizards/gcp.ts +1935 -0
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# `file` gates the header on the file existing: a 404 for a hashed
|
|
19
19
|
# URL (old page after a deploy switch) must not be cached for a year.
|
|
20
20
|
@content_hashed {
|
|
21
|
-
path_regexp content_hashed ^/(?:_app/immutable/.+|_assets/fonts/[^/]+/[0-9a-f]{16
|
|
21
|
+
path_regexp content_hashed ^/(?:_app/immutable/.+|_assets/fonts/[^/]+/[0-9a-f]{16}\.woff2|_assets/fonts/pinned/[0-9a-f]{64}\.[a-z]+(?:-[a-z]+)?\.[0-9a-f]{12}\.woff2|_assets/[a-z0-9][a-z0-9-]*(?:/[a-z][a-z0-9-]*)?\.[0-9a-f]{16}\.[a-z0-9]{2,5}|_caelo/plugin/[^/]+/[^/]+\.[0-9a-f]{12}\.(?:js|css))$
|
|
22
22
|
file
|
|
23
23
|
}
|
|
24
24
|
header @content_hashed Cache-Control "public, max-age=31536000, immutable"
|
package/caddy/Caddyfile.staging
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
# `file` gates the header on the file existing: a 404 for a hashed
|
|
23
23
|
# URL (old page after a deploy switch) must not be cached for a year.
|
|
24
24
|
@content_hashed {
|
|
25
|
-
path_regexp content_hashed ^/(?:_app/immutable/.+|_assets/fonts/[^/]+/[0-9a-f]{16
|
|
25
|
+
path_regexp content_hashed ^/(?:_app/immutable/.+|_assets/fonts/[^/]+/[0-9a-f]{16}\.woff2|_assets/fonts/pinned/[0-9a-f]{64}\.[a-z]+(?:-[a-z]+)?\.[0-9a-f]{12}\.woff2|_assets/[a-z0-9][a-z0-9-]*(?:/[a-z][a-z0-9-]*)?\.[0-9a-f]{16}\.[a-z0-9]{2,5}|_caelo/plugin/[^/]+/[^/]+\.[0-9a-f]{12}\.(?:js|css))$
|
|
26
26
|
file
|
|
27
27
|
}
|
|
28
28
|
header @content_hashed Cache-Control "public, max-age=31536000, immutable"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agent apply` — the target release's half of a self-hosted update (#696
|
|
3
|
+
* Phase 4c). The polling agent (agent/run.ts) claimed the request, verified
|
|
4
|
+
* the release's signed manifest and ran the refusal checks; it then starts
|
|
5
|
+
* THIS release's CLI, which performs the upgrade exactly like a hand-run
|
|
6
|
+
* `cms-provision upgrade` (self-hosted-upgrade.ts: verified digests, pg_dump
|
|
7
|
+
* backup, pull, migrations with the new admin image, health-checked roll,
|
|
8
|
+
* rollback) — narrated into the request's timeline — records how it ended,
|
|
9
|
+
* and re-pins the agent's systemd service to this release.
|
|
10
|
+
*
|
|
11
|
+
* It is never started by hand: it acts on a request the parent already
|
|
12
|
+
* claimed and holds the install's upgrade lock for.
|
|
13
|
+
*/
|
|
14
|
+
import type { PlatformUpdateTrigger } from "@caelo-cms/shared";
|
|
15
|
+
import type { SelfHostedUpgradeResult, UpgradeLog } from "../self-hosted-upgrade.js";
|
|
16
|
+
import { type UpdateEnd, type UpdateQueue } from "../upgrader-job.js";
|
|
17
|
+
import { type JobLog } from "../upgrader-reporter.js";
|
|
18
|
+
export interface AgentApplyDeps {
|
|
19
|
+
readonly queue: UpdateQueue;
|
|
20
|
+
readonly request: {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly targetVersion: string;
|
|
23
|
+
readonly trigger: PlatformUpdateTrigger;
|
|
24
|
+
};
|
|
25
|
+
/** This CLI's own release; must be the target. */
|
|
26
|
+
readonly agentVersion: string;
|
|
27
|
+
/** upgradeSelfHosted for the target, with the manifest's digests. */
|
|
28
|
+
readonly upgrade: (log: UpgradeLog) => Promise<SelfHostedUpgradeResult>;
|
|
29
|
+
/** Re-pin the agent's service to this release (agent/systemd.ts). */
|
|
30
|
+
readonly selfUpdate: () => Promise<{
|
|
31
|
+
ok: true;
|
|
32
|
+
} | {
|
|
33
|
+
ok: false;
|
|
34
|
+
error: string;
|
|
35
|
+
}>;
|
|
36
|
+
readonly log: JobLog;
|
|
37
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
/** The request's end state for an upgrade result. */
|
|
40
|
+
export declare function endForResult(result: SelfHostedUpgradeResult, trigger: PlatformUpdateTrigger): UpdateEnd;
|
|
41
|
+
/** Run the upgrade for the claimed request. Never throws. */
|
|
42
|
+
export declare function applyAgentUpdate(deps: AgentApplyDeps): Promise<{
|
|
43
|
+
exitCode: number;
|
|
44
|
+
}>;
|
|
45
|
+
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/agent/apply.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAErE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;KACzC,CAAC;IACF,kDAAkD;IAClD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACxE,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,qDAAqD;AACrD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,uBAAuB,EAC/B,OAAO,EAAE,qBAAqB,GAC7B,SAAS,CAgBX;AAED,6DAA6D;AAC7D,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA8D1F"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
import { recordUpdateEnd } from "../upgrader-job.js";
|
|
3
|
+
import { eventReporter } from "../upgrader-reporter.js";
|
|
4
|
+
/** The request's end state for an upgrade result. */
|
|
5
|
+
export function endForResult(result, trigger) {
|
|
6
|
+
if (result.ok)
|
|
7
|
+
return { status: "succeeded", reason: null, codes: [], pauseAutoUpdates: false };
|
|
8
|
+
const rolled = result.stage === "roll-admin" || result.stage === "roll-gateway";
|
|
9
|
+
const status = rolled && result.previousRunning ? "rolled_back" : "failed";
|
|
10
|
+
const lead = status === "rolled_back"
|
|
11
|
+
? "The new release did not pass its health check, so the previous release serves again."
|
|
12
|
+
: result.previousRunning
|
|
13
|
+
? "Nothing was changed; the previous release keeps serving."
|
|
14
|
+
: "The update stopped half-way and the previous release did not come back healthy — check `docker compose ps` on the server.";
|
|
15
|
+
return {
|
|
16
|
+
status,
|
|
17
|
+
reason: `${lead}\n${result.error}`.slice(0, 4000),
|
|
18
|
+
codes: [rolled && !result.previousRunning ? "rollback" : result.stage],
|
|
19
|
+
pauseAutoUpdates: trigger === "auto",
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** Run the upgrade for the claimed request. Never throws. */
|
|
23
|
+
export async function applyAgentUpdate(deps) {
|
|
24
|
+
const { queue, request, log } = deps;
|
|
25
|
+
const r = eventReporter((phase, level, message) => queue.event(request.id, phase, level, message), log, request.id);
|
|
26
|
+
const finish = async (end) => {
|
|
27
|
+
r.phase("finish");
|
|
28
|
+
if (end.status === "succeeded")
|
|
29
|
+
r.success(`Caelo ${request.targetVersion} is installed.`);
|
|
30
|
+
else
|
|
31
|
+
r.error(end.reason ?? end.status);
|
|
32
|
+
await r.flush();
|
|
33
|
+
const recorded = await recordUpdateEnd(queue, request.id, end, log, deps.sleep);
|
|
34
|
+
return { exitCode: recorded && end.status === "succeeded" ? 0 : 1 };
|
|
35
|
+
};
|
|
36
|
+
if (deps.agentVersion !== request.targetVersion) {
|
|
37
|
+
return finish({
|
|
38
|
+
status: "failed",
|
|
39
|
+
reason: `Nothing was changed: the installer of Caelo ${deps.agentVersion} was started for ${request.targetVersion}.`,
|
|
40
|
+
codes: ["apply"],
|
|
41
|
+
pauseAutoUpdates: request.trigger === "auto",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
let result;
|
|
45
|
+
try {
|
|
46
|
+
r.phase("start");
|
|
47
|
+
r.info(`The Caelo ${request.targetVersion} installer took over.`);
|
|
48
|
+
result = await deps.upgrade({
|
|
49
|
+
step: (m) => {
|
|
50
|
+
r.step(m);
|
|
51
|
+
},
|
|
52
|
+
info: (m) => r.info(m),
|
|
53
|
+
warn: (m) => r.warn(m),
|
|
54
|
+
error: (m) => r.error(m),
|
|
55
|
+
phase: (p) => r.phase(p),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
return finish({
|
|
60
|
+
status: "failed",
|
|
61
|
+
reason: `The installer stopped unexpectedly: ${e instanceof Error ? e.message : String(e)}. Check \`docker compose ps\` on the server.`,
|
|
62
|
+
codes: ["internal"],
|
|
63
|
+
pauseAutoUpdates: request.trigger === "auto",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (result.ok) {
|
|
67
|
+
if (result.status === "already-current") {
|
|
68
|
+
r.info(`Caelo ${result.version} was already installed; the containers are healthy.`);
|
|
69
|
+
}
|
|
70
|
+
r.phase("self-update");
|
|
71
|
+
const pinned = await deps.selfUpdate().catch((e) => ({
|
|
72
|
+
ok: false,
|
|
73
|
+
error: e instanceof Error ? e.message : String(e),
|
|
74
|
+
}));
|
|
75
|
+
if (pinned.ok)
|
|
76
|
+
r.info(`The update agent itself now runs ${request.targetVersion}.`);
|
|
77
|
+
else {
|
|
78
|
+
r.warn(`The update agent could not update itself (${pinned.error}); it keeps working with its current version.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return finish(endForResult(result, request.trigger));
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/agent/apply.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAkBnC,OAAO,EAAE,eAAe,EAAoC,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAE,aAAa,EAAe,MAAM,yBAAyB,CAAC;AAmBrE,qDAAqD;AACrD,MAAM,UAAU,YAAY,CAC1B,MAA+B,EAC/B,OAA8B;IAE9B,IAAI,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;IAChG,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,KAAK,YAAY,IAAI,MAAM,CAAC,KAAK,KAAK,cAAc,CAAC;IAChF,MAAM,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC3E,MAAM,IAAI,GACR,MAAM,KAAK,aAAa;QACtB,CAAC,CAAC,sFAAsF;QACxF,CAAC,CAAC,MAAM,CAAC,eAAe;YACtB,CAAC,CAAC,0DAA0D;YAC5D,CAAC,CAAC,2HAA2H,CAAC;IACpI,OAAO;QACL,MAAM;QACN,MAAM,EAAE,GAAG,IAAI,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;QACjD,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACtE,gBAAgB,EAAE,OAAO,KAAK,MAAM;KACrC,CAAC;AACJ,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAoB;IACzD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,GAAG,aAAa,CACrB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EACzE,GAAG,EACH,OAAO,CAAC,EAAE,CACX,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,EAAE,GAAc,EAAiC,EAAE;QACrE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClB,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW;YAAE,CAAC,CAAC,OAAO,CAAC,SAAS,OAAO,CAAC,aAAa,gBAAgB,CAAC,CAAC;;YACrF,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAChF,OAAO,EAAE,QAAQ,EAAE,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,CAAC,CAAC;IAEF,IAAI,IAAI,CAAC,YAAY,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC;QAChD,OAAO,MAAM,CAAC;YACZ,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,+CAA+C,IAAI,CAAC,YAAY,oBAAoB,OAAO,CAAC,aAAa,GAAG;YACpH,KAAK,EAAE,CAAC,OAAO,CAAC;YAChB,gBAAgB,EAAE,OAAO,CAAC,OAAO,KAAK,MAAM;SAC7C,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAA+B,CAAC;IACpC,IAAI,CAAC;QACH,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjB,CAAC,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,aAAa,uBAAuB,CAAC,CAAC;QAClE,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC1B,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;gBACV,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACZ,CAAC;YACD,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACtB,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACtB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACxB,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;SACzB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;YACZ,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,uCAAuC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,8CAA8C;YACvI,KAAK,EAAE,CAAC,UAAU,CAAC;YACnB,gBAAgB,EAAE,OAAO,CAAC,OAAO,KAAK,MAAM;SAC7C,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,IAAI,MAAM,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;YACxC,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,OAAO,qDAAqD,CAAC,CAAC;QACvF,CAAC;QACD,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC;YAC5D,EAAE,EAAE,KAAc;YAClB,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;SAClD,CAAC,CAAC,CAAC;QACJ,IAAI,MAAM,CAAC,EAAE;YAAE,CAAC,CAAC,IAAI,CAAC,oCAAoC,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC;aAC/E,CAAC;YACJ,CAAC,CAAC,IAAI,CACJ,6CAA6C,MAAM,CAAC,KAAK,+CAA+C,CACzG,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { HostRunner } from "../self-hosted-release.js";
|
|
2
|
+
/** Where Caelo's packages are built (the provenance's workflow repository). */
|
|
3
|
+
export declare const SOURCE_REPOSITORY = "https://github.com/caelo-cms/caelo-cms";
|
|
4
|
+
/** The Caelo packages the CLI runs; both must carry the release's provenance. */
|
|
5
|
+
export declare const CAELO_CLI_PACKAGES: readonly ["@caelo-cms/provisioning", "@caelo-cms/shared"];
|
|
6
|
+
/** Why the CLI of a release was not trusted. */
|
|
7
|
+
export interface CliProvenanceError {
|
|
8
|
+
readonly code: "npm-missing" | "npm-install" | "audit-signatures" | "version" | "provenance";
|
|
9
|
+
readonly message: string;
|
|
10
|
+
}
|
|
11
|
+
export type VerifiedCli = {
|
|
12
|
+
readonly ok: true;
|
|
13
|
+
readonly cliPath: string;
|
|
14
|
+
readonly dir: string;
|
|
15
|
+
} | {
|
|
16
|
+
readonly ok: false;
|
|
17
|
+
readonly error: CliProvenanceError;
|
|
18
|
+
};
|
|
19
|
+
/** `.caelo/agent/cli/` — the verified CLI installs, one folder per release. */
|
|
20
|
+
export declare function verifiedCliRoot(caeloDir: string): string;
|
|
21
|
+
/** The folder of release `version`'s verified CLI. */
|
|
22
|
+
export declare function verifiedCliDir(caeloDir: string, version: string): string;
|
|
23
|
+
/** The CLI entry point inside {@link verifiedCliDir}. */
|
|
24
|
+
export declare function verifiedCliPath(dir: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Check one package's npm provenance attestation: SLSA v1, built from
|
|
27
|
+
* {@link SOURCE_REPOSITORY} at `refs/tags/v<version>`, for this exact
|
|
28
|
+
* package version.
|
|
29
|
+
*
|
|
30
|
+
* @returns null when it checks out, else why not
|
|
31
|
+
*/
|
|
32
|
+
export declare function provenanceProblem(name: string, version: string, fetchImpl?: typeof fetch): Promise<string | null>;
|
|
33
|
+
/**
|
|
34
|
+
* Install release `version`'s CLI into `dir` (replacing what is there) and
|
|
35
|
+
* verify it. Nothing in it runs before the checks passed: npm's lifecycle
|
|
36
|
+
* scripts are off.
|
|
37
|
+
*/
|
|
38
|
+
export declare function installVerifiedCli(version: string, dir: string, deps: {
|
|
39
|
+
readonly runner: HostRunner;
|
|
40
|
+
readonly fetchImpl?: typeof fetch;
|
|
41
|
+
}): Promise<VerifiedCli>;
|
|
42
|
+
//# sourceMappingURL=cli-provenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-provenance.d.ts","sourceRoot":"","sources":["../../src/agent/cli-provenance.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,2CAA2C,CAAC;AAE1E,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,2DAA4D,CAAC;AAE5F,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,kBAAkB,GAAG,SAAS,GAAG,YAAY,CAAC;IAC7F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAE/D,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AASD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuCxB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAAE,GACvE,OAAO,CAAC,WAAW,CAAC,CAkEtB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/**
|
|
3
|
+
* The target release's provisioning CLI, installed and VERIFIED before the
|
|
4
|
+
* update agent runs it (#696 Phase 4c, maintainer decision on #721). The
|
|
5
|
+
* signed release manifest proves a release exists and is installable; this
|
|
6
|
+
* proves the code that installs it is that release's: the same checks the
|
|
7
|
+
* Cloud Shell runner (`run.sh` in caelo-cms/install) makes.
|
|
8
|
+
*
|
|
9
|
+
* 1. `npm install` of exactly `@caelo-cms/provisioning@<v>` (with
|
|
10
|
+
* `@caelo-cms/shared` pinned to the same version, lifecycle scripts
|
|
11
|
+
* off) into a private folder under `.caelo/agent/cli/`;
|
|
12
|
+
* 2. `npm audit signatures` — the registry signatures and Sigstore
|
|
13
|
+
* provenance attestations of every installed package;
|
|
14
|
+
* 3. both Caelo packages are the asked-for version, and their SLSA
|
|
15
|
+
* provenance names caelo-cms/caelo-cms at `refs/tags/v<v>`.
|
|
16
|
+
*
|
|
17
|
+
* Any failure is a structured {@link CliProvenanceError}; there is no
|
|
18
|
+
* fallback to an unverified `bunx` run.
|
|
19
|
+
*/
|
|
20
|
+
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
/** Where Caelo's packages are built (the provenance's workflow repository). */
|
|
23
|
+
export const SOURCE_REPOSITORY = "https://github.com/caelo-cms/caelo-cms";
|
|
24
|
+
/** The Caelo packages the CLI runs; both must carry the release's provenance. */
|
|
25
|
+
export const CAELO_CLI_PACKAGES = ["@caelo-cms/provisioning", "@caelo-cms/shared"];
|
|
26
|
+
/** `.caelo/agent/cli/` — the verified CLI installs, one folder per release. */
|
|
27
|
+
export function verifiedCliRoot(caeloDir) {
|
|
28
|
+
return join(caeloDir, "agent", "cli");
|
|
29
|
+
}
|
|
30
|
+
/** The folder of release `version`'s verified CLI. */
|
|
31
|
+
export function verifiedCliDir(caeloDir, version) {
|
|
32
|
+
return join(verifiedCliRoot(caeloDir), `caelo-${version}`);
|
|
33
|
+
}
|
|
34
|
+
/** The CLI entry point inside {@link verifiedCliDir}. */
|
|
35
|
+
export function verifiedCliPath(dir) {
|
|
36
|
+
return join(dir, "node_modules", "@caelo-cms", "provisioning", "dist", "cli.js");
|
|
37
|
+
}
|
|
38
|
+
const fail = (code, message) => ({
|
|
39
|
+
ok: false,
|
|
40
|
+
error: { code, message },
|
|
41
|
+
});
|
|
42
|
+
const tail = (s) => s.trim().split("\n").slice(-6).join("\n").slice(0, 800);
|
|
43
|
+
/**
|
|
44
|
+
* Check one package's npm provenance attestation: SLSA v1, built from
|
|
45
|
+
* {@link SOURCE_REPOSITORY} at `refs/tags/v<version>`, for this exact
|
|
46
|
+
* package version.
|
|
47
|
+
*
|
|
48
|
+
* @returns null when it checks out, else why not
|
|
49
|
+
*/
|
|
50
|
+
export async function provenanceProblem(name, version, fetchImpl = fetch) {
|
|
51
|
+
const url = `https://registry.npmjs.org/-/npm/v1/attestations/${encodeURIComponent(name)}@${version}`;
|
|
52
|
+
let body;
|
|
53
|
+
try {
|
|
54
|
+
const res = await fetchImpl(url);
|
|
55
|
+
if (!res.ok)
|
|
56
|
+
return `${name}@${version}: no provenance attestation (${url}: HTTP ${res.status})`;
|
|
57
|
+
body = (await res.json());
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
return `${name}@${version}: the attestations could not be fetched (${e instanceof Error ? e.message : String(e)})`;
|
|
61
|
+
}
|
|
62
|
+
const slsa = body.attestations?.find((a) => a.predicateType === "https://slsa.dev/provenance/v1");
|
|
63
|
+
const payload = slsa?.bundle
|
|
64
|
+
?.dsseEnvelope?.payload;
|
|
65
|
+
if (!payload)
|
|
66
|
+
return `${name}@${version}: no SLSA provenance`;
|
|
67
|
+
let statement;
|
|
68
|
+
try {
|
|
69
|
+
statement = JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return `${name}@${version}: the provenance statement is not JSON`;
|
|
73
|
+
}
|
|
74
|
+
const workflow = statement.predicate?.buildDefinition?.externalParameters?.workflow ?? {};
|
|
75
|
+
const subjects = (statement.subject ?? []).map((s) => s.name);
|
|
76
|
+
const wantSubject = `pkg:npm/${name.replaceAll("@", "%40")}@${version}`;
|
|
77
|
+
if (workflow.repository !== SOURCE_REPOSITORY ||
|
|
78
|
+
workflow.ref !== `refs/tags/v${version}` ||
|
|
79
|
+
!subjects.includes(wantSubject)) {
|
|
80
|
+
return `${name}@${version} was not built by ${SOURCE_REPOSITORY} at refs/tags/v${version} (provenance: ${workflow.repository ?? "?"} ${workflow.ref ?? "?"}, ${subjects.join(",")})`;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Install release `version`'s CLI into `dir` (replacing what is there) and
|
|
86
|
+
* verify it. Nothing in it runs before the checks passed: npm's lifecycle
|
|
87
|
+
* scripts are off.
|
|
88
|
+
*/
|
|
89
|
+
export async function installVerifiedCli(version, dir, deps) {
|
|
90
|
+
const probe = await deps.runner.run(["npm", "--version"]);
|
|
91
|
+
if (probe.exitCode !== 0) {
|
|
92
|
+
return fail("npm-missing", "npm is not installed on the server (or not on the agent's PATH); the update agent needs it to verify the provenance of the Caelo release it installs. Install Node.js + npm, then run `agent install` again.");
|
|
93
|
+
}
|
|
94
|
+
rmSync(dir, { recursive: true, force: true });
|
|
95
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
96
|
+
// Exact versions for both Caelo packages: provisioning depends on
|
|
97
|
+
// ^<version> of shared, which could otherwise resolve to a newer one.
|
|
98
|
+
writeFileSync(join(dir, "package.json"), JSON.stringify({
|
|
99
|
+
name: "caelo-agent-cli",
|
|
100
|
+
private: true,
|
|
101
|
+
dependencies: { "@caelo-cms/provisioning": version },
|
|
102
|
+
overrides: { "@caelo-cms/shared": version },
|
|
103
|
+
}, null, 2));
|
|
104
|
+
const install = await deps.runner.run([
|
|
105
|
+
"npm",
|
|
106
|
+
"install",
|
|
107
|
+
"--prefix",
|
|
108
|
+
dir,
|
|
109
|
+
"--ignore-scripts",
|
|
110
|
+
"--no-audit",
|
|
111
|
+
"--no-fund",
|
|
112
|
+
"--loglevel=error",
|
|
113
|
+
]);
|
|
114
|
+
if (install.exitCode !== 0) {
|
|
115
|
+
return fail("npm-install", `npm could not install @caelo-cms/provisioning@${version}: ${tail(install.stderr || install.stdout)}`);
|
|
116
|
+
}
|
|
117
|
+
const audit = await deps.runner.run(["npm", "audit", "signatures", "--prefix", dir]);
|
|
118
|
+
if (audit.exitCode !== 0) {
|
|
119
|
+
return fail("audit-signatures", `npm audit signatures rejected the packages of Caelo ${version}: ${tail(audit.stderr || audit.stdout)}`);
|
|
120
|
+
}
|
|
121
|
+
for (const name of CAELO_CLI_PACKAGES) {
|
|
122
|
+
let installed;
|
|
123
|
+
try {
|
|
124
|
+
installed = JSON.parse(readFileSync(join(dir, "node_modules", name, "package.json"), "utf8")).version;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
installed = undefined;
|
|
128
|
+
}
|
|
129
|
+
if (installed !== version) {
|
|
130
|
+
return fail("version", `${name}: installed ${installed ?? "nothing"}, expected ${version}`);
|
|
131
|
+
}
|
|
132
|
+
const problem = await provenanceProblem(name, version, deps.fetchImpl);
|
|
133
|
+
if (problem)
|
|
134
|
+
return fail("provenance", problem);
|
|
135
|
+
}
|
|
136
|
+
return { ok: true, cliPath: verifiedCliPath(dir), dir };
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=cli-provenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-provenance.js","sourceRoot":"","sources":["../../src/agent/cli-provenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { ReleaseImages } from "../compose.js";
|
|
2
|
+
import { type HostRunner } from "../self-hosted-release.js";
|
|
3
|
+
import type { ConvergeOutcome } from "../self-hosted-roles.js";
|
|
4
|
+
import { type AgentConfig } from "./config.js";
|
|
5
|
+
import { type AgentHost } from "./systemd.js";
|
|
6
|
+
/** What the CLI owns that the agent commands need. */
|
|
7
|
+
export interface AgentCliContext {
|
|
8
|
+
readonly caeloDir: string;
|
|
9
|
+
readonly domain: string;
|
|
10
|
+
readonly imageMode: "release" | "dev" | undefined;
|
|
11
|
+
/** config.json → agent. */
|
|
12
|
+
agent(): AgentConfig | undefined;
|
|
13
|
+
/** Persist config.json → agent (undefined removes it). */
|
|
14
|
+
saveAgent(agent: AgentConfig | undefined): void;
|
|
15
|
+
/** Re-write the Compose file (with the agent's port) and bootstrap.sh. */
|
|
16
|
+
emitConfig(): void;
|
|
17
|
+
/** The role convergence as the superuser, including the agent's login. */
|
|
18
|
+
convergeRoles(): Promise<ConvergeOutcome>;
|
|
19
|
+
/** The Compose file for `images` from config.json. */
|
|
20
|
+
renderCompose(images: ReleaseImages): string;
|
|
21
|
+
randomSecret(): string;
|
|
22
|
+
}
|
|
23
|
+
/** The notice printed before the one restart Postgres gets for the agent. */
|
|
24
|
+
export declare const POSTGRES_RESTART_NOTICE = "Postgres restarts once, a few seconds of downtime: it is now also published on 127.0.0.1 for the update agent. The admin reconnects by itself.";
|
|
25
|
+
/**
|
|
26
|
+
* Whether the running Postgres container already publishes `port` on the
|
|
27
|
+
* loopback interface (`docker compose port postgres 5432`).
|
|
28
|
+
*/
|
|
29
|
+
export declare function postgresPublishedOnLoopback(ctx: Pick<AgentCliContext, "caeloDir">, runner: HostRunner, port: number): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Apply the agent's database side to a RUNNING install: the login, then —
|
|
32
|
+
* only the first time, when the container does not publish the agent's
|
|
33
|
+
* port yet — one `up -d postgres` to publish it (#721: Postgres restarts
|
|
34
|
+
* once, announced first). Re-running finds the port published and leaves
|
|
35
|
+
* Postgres alone; `agent run` / `agent apply` never get here.
|
|
36
|
+
*/
|
|
37
|
+
export declare function applyDatabaseSide(ctx: Pick<AgentCliContext, "caeloDir" | "convergeRoles">, runner: HostRunner, port: number, opts?: {
|
|
38
|
+
readonly notice?: (m: string) => void;
|
|
39
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
40
|
+
}): Promise<{
|
|
41
|
+
ok: true;
|
|
42
|
+
restarted: boolean;
|
|
43
|
+
} | {
|
|
44
|
+
ok: false;
|
|
45
|
+
error: string;
|
|
46
|
+
}>;
|
|
47
|
+
export type SetUpAgentResult = {
|
|
48
|
+
readonly kind: "installed";
|
|
49
|
+
readonly unit: string;
|
|
50
|
+
readonly version: string;
|
|
51
|
+
readonly warnings: readonly string[];
|
|
52
|
+
} | {
|
|
53
|
+
readonly kind: "skipped";
|
|
54
|
+
readonly reason: string;
|
|
55
|
+
} | {
|
|
56
|
+
readonly kind: "failed";
|
|
57
|
+
readonly error: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Set the agent up, or bring it up to date — idempotent, for `agent
|
|
61
|
+
* install`, `init` and `upgrade`. With `database: "live"` the install's
|
|
62
|
+
* Postgres runs and gets the login + port now; with `"fresh"` (init) the
|
|
63
|
+
* volume is new and bootstrap.sh creates the login on first start.
|
|
64
|
+
*
|
|
65
|
+
* Never pins an older release than the one already installed.
|
|
66
|
+
*/
|
|
67
|
+
export declare function setUpAgent(ctx: AgentCliContext, opts: {
|
|
68
|
+
readonly database: "live" | "fresh";
|
|
69
|
+
readonly requestedPort?: number;
|
|
70
|
+
/** `agent install` re-enables an uninstalled agent; init/upgrade respect it. */
|
|
71
|
+
readonly explicit: boolean;
|
|
72
|
+
readonly runner?: HostRunner;
|
|
73
|
+
readonly host?: AgentHost;
|
|
74
|
+
}): Promise<SetUpAgentResult>;
|
|
75
|
+
/** Print what {@link setUpAgent} did, for init / upgrade / agent install. */
|
|
76
|
+
export declare function reportAgentSetup(result: SetUpAgentResult): void;
|
|
77
|
+
/** `agent <sub>`. */
|
|
78
|
+
export declare function agentCommand(argv: readonly string[], ctx: AgentCliContext): Promise<number>;
|
|
79
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/agent/command.ts"],"names":[],"mappings":"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"}
|