@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.
- package/dist/adc-impersonation.d.ts +28 -0
- package/dist/adc-impersonation.d.ts.map +1 -0
- package/dist/adc-impersonation.js +148 -0
- package/dist/adc-impersonation.js.map +1 -0
- package/dist/checkpoint-secrets.d.ts.map +1 -1
- package/dist/checkpoint-secrets.js +2 -1
- package/dist/checkpoint-secrets.js.map +1 -1
- package/dist/cli.js +202 -33
- package/dist/cli.js.map +1 -1
- package/dist/compose.d.ts +45 -0
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +112 -29
- package/dist/compose.js.map +1 -1
- package/dist/gcloud-retry.d.ts +5 -1
- package/dist/gcloud-retry.d.ts.map +1 -1
- package/dist/gcloud-retry.js.map +1 -1
- package/dist/gcloud.d.ts +2 -1
- package/dist/gcloud.d.ts.map +1 -1
- package/dist/gcloud.js +11 -13
- package/dist/gcloud.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/infra-contract.d.ts +24 -0
- package/dist/infra-contract.d.ts.map +1 -0
- package/dist/infra-contract.js +25 -0
- package/dist/infra-contract.js.map +1 -0
- package/dist/install-state.d.ts +66 -2
- package/dist/install-state.d.ts.map +1 -1
- package/dist/install-state.js +162 -22
- package/dist/install-state.js.map +1 -1
- package/dist/lifecycle.d.ts +6 -0
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +189 -819
- package/dist/lifecycle.js.map +1 -1
- package/dist/migration-runner.d.ts +3 -0
- package/dist/migration-runner.d.ts.map +1 -1
- package/dist/migration-runner.js +7 -5
- package/dist/migration-runner.js.map +1 -1
- package/dist/ops-backend.d.ts +46 -0
- package/dist/ops-backend.d.ts.map +1 -0
- package/dist/ops-backend.js +370 -0
- package/dist/ops-backend.js.map +1 -0
- package/dist/provisioner-identity.d.ts +103 -0
- package/dist/provisioner-identity.d.ts.map +1 -0
- package/dist/provisioner-identity.js +323 -0
- package/dist/provisioner-identity.js.map +1 -0
- package/dist/regions.d.ts.map +1 -1
- package/dist/regions.js +2 -1
- package/dist/regions.js.map +1 -1
- package/dist/release-contract.d.ts +37 -0
- package/dist/release-contract.d.ts.map +1 -0
- package/dist/release-contract.js +55 -0
- package/dist/release-contract.js.map +1 -0
- package/dist/release-manifest.d.ts +140 -0
- package/dist/release-manifest.d.ts.map +1 -0
- package/dist/release-manifest.js +319 -0
- package/dist/release-manifest.js.map +1 -0
- package/dist/self-command.d.ts +16 -0
- package/dist/self-command.d.ts.map +1 -0
- package/dist/self-command.js +20 -0
- package/dist/self-command.js.map +1 -0
- package/dist/self-hosted-release.d.ts +81 -0
- package/dist/self-hosted-release.d.ts.map +1 -0
- package/dist/self-hosted-release.js +148 -0
- package/dist/self-hosted-release.js.map +1 -0
- package/dist/self-hosted-upgrade.d.ts +91 -0
- package/dist/self-hosted-upgrade.d.ts.map +1 -0
- package/dist/self-hosted-upgrade.js +355 -0
- package/dist/self-hosted-upgrade.js.map +1 -0
- package/dist/stack-converge.d.ts.map +1 -1
- package/dist/stack-converge.js +2 -1
- package/dist/stack-converge.js.map +1 -1
- package/dist/state-attach.d.ts +23 -0
- package/dist/state-attach.d.ts.map +1 -0
- package/dist/state-attach.js +112 -0
- package/dist/state-attach.js.map +1 -0
- package/dist/state-backend.d.ts +114 -0
- package/dist/state-backend.d.ts.map +1 -0
- package/dist/state-backend.js +200 -0
- package/dist/state-backend.js.map +1 -0
- package/dist/state-command.d.ts +20 -0
- package/dist/state-command.d.ts.map +1 -0
- package/dist/state-command.js +237 -0
- package/dist/state-command.js.map +1 -0
- package/dist/state-migrate.d.ts +121 -0
- package/dist/state-migrate.d.ts.map +1 -0
- package/dist/state-migrate.js +290 -0
- package/dist/state-migrate.js.map +1 -0
- package/dist/state-pulumi.d.ts +17 -0
- package/dist/state-pulumi.d.ts.map +1 -0
- package/dist/state-pulumi.js +218 -0
- package/dist/state-pulumi.js.map +1 -0
- package/dist/state-store.d.ts +82 -0
- package/dist/state-store.d.ts.map +1 -0
- package/dist/state-store.js +205 -0
- package/dist/state-store.js.map +1 -0
- package/dist/upgrade/app-roll.d.ts +164 -0
- package/dist/upgrade/app-roll.d.ts.map +1 -0
- package/dist/upgrade/app-roll.js +270 -0
- package/dist/upgrade/app-roll.js.map +1 -0
- package/dist/upgrade/backup.d.ts +48 -0
- package/dist/upgrade/backup.d.ts.map +1 -0
- package/dist/upgrade/backup.js +71 -0
- package/dist/upgrade/backup.js.map +1 -0
- package/dist/upgrade/converge.d.ts +45 -0
- package/dist/upgrade/converge.d.ts.map +1 -0
- package/dist/upgrade/converge.js +287 -0
- package/dist/upgrade/converge.js.map +1 -0
- package/dist/upgrade/gcp-lookup.d.ts +23 -0
- package/dist/upgrade/gcp-lookup.d.ts.map +1 -0
- package/dist/upgrade/gcp-lookup.js +95 -0
- package/dist/upgrade/gcp-lookup.js.map +1 -0
- package/dist/upgrade/health.d.ts +99 -0
- package/dist/upgrade/health.d.ts.map +1 -0
- package/dist/upgrade/health.js +214 -0
- package/dist/upgrade/health.js.map +1 -0
- package/dist/upgrade/release-images.d.ts +125 -0
- package/dist/upgrade/release-images.d.ts.map +1 -0
- package/dist/upgrade/release-images.js +315 -0
- package/dist/upgrade/release-images.js.map +1 -0
- package/dist/upgrade/reporter.d.ts +17 -0
- package/dist/upgrade/reporter.d.ts.map +1 -0
- package/dist/upgrade/reporter.js +28 -0
- package/dist/upgrade/reporter.js.map +1 -0
- package/dist/upgrade/upgrade.d.ts +79 -0
- package/dist/upgrade/upgrade.d.ts.map +1 -0
- package/dist/upgrade/upgrade.js +105 -0
- package/dist/upgrade/upgrade.js.map +1 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +7 -3
- package/dist/wizard.js.map +1 -1
- package/dist/wizards/gcp-cost.d.ts.map +1 -1
- package/dist/wizards/gcp-cost.js +7 -1
- package/dist/wizards/gcp-cost.js.map +1 -1
- package/dist/wizards/gcp-pulumi.d.ts +104 -8
- package/dist/wizards/gcp-pulumi.d.ts.map +1 -1
- package/dist/wizards/gcp-pulumi.js +159 -50
- package/dist/wizards/gcp-pulumi.js.map +1 -1
- package/dist/wizards/gcp.d.ts.map +1 -1
- package/dist/wizards/gcp.js +246 -78
- package/dist/wizards/gcp.js.map +1 -1
- package/package.json +4 -3
- package/stacks/self-hosted/README.md +4 -0
- package/stacks/self-hosted/index.ts +10 -2
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
import { mcpIapServiceAccountEmail } from "../gcp-names.js";
|
|
3
|
+
function parseJson(text) {
|
|
4
|
+
try {
|
|
5
|
+
return JSON.parse(text);
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Judge the admin's deep health answer.
|
|
13
|
+
*
|
|
14
|
+
* @returns the version the admin runs on success
|
|
15
|
+
*/
|
|
16
|
+
export function evaluateAdminDeepHealth(status, text, expectedVersion) {
|
|
17
|
+
const body = parseJson(text);
|
|
18
|
+
if (!body)
|
|
19
|
+
return { ok: false, error: `admin answered HTTP ${status} without JSON` };
|
|
20
|
+
const m = body.migrations;
|
|
21
|
+
// Pending migrations come with a 503; name them rather than "unhealthy".
|
|
22
|
+
for (const [db, state] of [
|
|
23
|
+
["cms_admin", m?.admin],
|
|
24
|
+
["cms_public", m?.public],
|
|
25
|
+
]) {
|
|
26
|
+
if (state && state.pending !== 0) {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
error: `${db} is missing ${state.pending} migration(s) the new admin image ships (applied head: ${state.head ?? "none"})`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (status !== 200 || body.ok !== true) {
|
|
34
|
+
const why = body.error ? `${body.error.kind ?? "?"}: ${body.error.message ?? ""}` : "no reason";
|
|
35
|
+
return { ok: false, error: `admin reports unhealthy (HTTP ${status}, ${why})` };
|
|
36
|
+
}
|
|
37
|
+
if (!body.version)
|
|
38
|
+
return { ok: false, error: "admin reported no version" };
|
|
39
|
+
if (expectedVersion !== null && body.version !== expectedVersion) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
error: `admin runs ${body.version}, the roll targeted ${expectedVersion}`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (!m?.admin || !m.public) {
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
error: "admin did not report its migration state (its image predates the deep health check; pass --skip-health-check to roll to such a release)",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
ok: true,
|
|
53
|
+
version: body.version,
|
|
54
|
+
detail: `admin ${body.version}, migrations at ${m.admin.head ?? "?"} / ${m.public.head ?? "?"}`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** Judge the gateway's deep health answer against the version the admin runs. */
|
|
58
|
+
export function evaluateGatewayDeepHealth(status, text, expectedVersion) {
|
|
59
|
+
const body = parseJson(text);
|
|
60
|
+
if (!body)
|
|
61
|
+
return { ok: false, error: `gateway answered HTTP ${status} without JSON` };
|
|
62
|
+
if (status !== 200 || body.ok !== true) {
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
error: `gateway reports unhealthy (HTTP ${status}, ${body.error?.kind ?? "no reason"})`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (body.version !== expectedVersion) {
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
error: `gateway runs ${body.version ?? "an unknown version"}, the admin runs ${expectedVersion}`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return { ok: true, detail: `gateway ${body.version}` };
|
|
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 function healthOrigins(target) {
|
|
83
|
+
return target.provider === "gcp"
|
|
84
|
+
? { admin: `https://admin.${target.domain}`, gateway: `https://${target.domain}` }
|
|
85
|
+
: {
|
|
86
|
+
admin: new URL(target.adminServiceUrl).origin,
|
|
87
|
+
gateway: new URL(target.gatewayServiceUrl).origin,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const JWT_LIFETIME_S = 600;
|
|
91
|
+
const IAM_CREDENTIALS = "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts";
|
|
92
|
+
/** The IAP-backed probe of a gcp / gcp-firebase install. */
|
|
93
|
+
export function createIapHealthProbe(target, deps) {
|
|
94
|
+
const origins = healthOrigins(target);
|
|
95
|
+
const signer = mcpIapServiceAccountEmail(target.projectId);
|
|
96
|
+
const attempts = deps.attempts ?? 12;
|
|
97
|
+
const intervalMs = deps.intervalMs ?? 5_000;
|
|
98
|
+
const now = deps.now ?? (() => Math.floor(Date.now() / 1000));
|
|
99
|
+
/**
|
|
100
|
+
* A JWT IAP accepts for the admin origin, signed as the MCP service
|
|
101
|
+
* account. Never throws: a transport failure is a failed outcome, so the
|
|
102
|
+
* retries and the app-roll's rollback still run.
|
|
103
|
+
*/
|
|
104
|
+
async function iapToken() {
|
|
105
|
+
try {
|
|
106
|
+
return await signIapToken();
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
return {
|
|
110
|
+
ok: false,
|
|
111
|
+
error: `could not sign an IAP credential as ${signer}: ${e instanceof Error ? e.message : String(e)}`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function signIapToken() {
|
|
116
|
+
const token = await deps.run(["auth", "print-access-token"]);
|
|
117
|
+
const bearer = token.ok ? token.stdout.trim() : "";
|
|
118
|
+
if (!bearer) {
|
|
119
|
+
return {
|
|
120
|
+
ok: false,
|
|
121
|
+
error: `gcloud auth print-access-token: ${token.stderr.trim() || "empty"}`,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const iat = now();
|
|
125
|
+
const res = await deps.http(`${IAM_CREDENTIALS}/${encodeURIComponent(signer)}:signJwt`, {
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: { Authorization: `Bearer ${bearer}`, "Content-Type": "application/json" },
|
|
128
|
+
body: JSON.stringify({
|
|
129
|
+
payload: JSON.stringify({
|
|
130
|
+
iss: signer,
|
|
131
|
+
sub: signer,
|
|
132
|
+
aud: `${origins.admin}/*`,
|
|
133
|
+
iat,
|
|
134
|
+
exp: iat + JWT_LIFETIME_S,
|
|
135
|
+
}),
|
|
136
|
+
}),
|
|
137
|
+
});
|
|
138
|
+
const text = await res.text();
|
|
139
|
+
if (!res.ok) {
|
|
140
|
+
return {
|
|
141
|
+
ok: false,
|
|
142
|
+
error: `could not sign an IAP credential as ${signer} (HTTP ${res.status}). Your account needs roles/iam.serviceAccountTokenCreator on it — upgrade's converge step grants it to every IAP-allowlisted user. ${text.slice(0, 300)}`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const jwt = parseJson(text)?.signedJwt;
|
|
146
|
+
return jwt ? { ok: true, jwt } : { ok: false, error: "signJwt returned no signedJwt" };
|
|
147
|
+
}
|
|
148
|
+
async function get(url, headers) {
|
|
149
|
+
try {
|
|
150
|
+
const res = await deps.http(url, { method: "GET", headers });
|
|
151
|
+
return { reached: true, status: res.status, text: await res.text() };
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
return { reached: false, error: e instanceof Error ? e.message : String(e) };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
async baseline() {
|
|
159
|
+
const token = await iapToken();
|
|
160
|
+
if (!token.ok)
|
|
161
|
+
return token;
|
|
162
|
+
const auth = { Authorization: `Bearer ${token.jwt}` };
|
|
163
|
+
const admin = await get(`${origins.admin}/_caelo/health`, auth);
|
|
164
|
+
if (!admin.reached) {
|
|
165
|
+
return { ok: false, error: `admin unreachable at ${origins.admin}: ${admin.error}` };
|
|
166
|
+
}
|
|
167
|
+
// The serving (old) admin answers its shallow health JSON. Anything
|
|
168
|
+
// else — IAP's login redirect, a 401/403, an HTML error page — means
|
|
169
|
+
// the probe would not see the new revision either.
|
|
170
|
+
const body = parseJson(admin.text);
|
|
171
|
+
if (!body?.version) {
|
|
172
|
+
return {
|
|
173
|
+
ok: false,
|
|
174
|
+
error: `admin at ${origins.admin} did not answer its health check (HTTP ${admin.status}); IAP may not admit ${signer}`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const gateway = await get(`${origins.gateway}/api/_caelo/health`, {});
|
|
178
|
+
if (!gateway.reached) {
|
|
179
|
+
return { ok: false, error: `gateway unreachable at ${origins.gateway}: ${gateway.error}` };
|
|
180
|
+
}
|
|
181
|
+
return { ok: true, detail: `admin ${body.version} and gateway reachable` };
|
|
182
|
+
},
|
|
183
|
+
async deep(expect) {
|
|
184
|
+
let last = { ok: false, error: "no attempt made" };
|
|
185
|
+
for (let i = 0; i < attempts; i++) {
|
|
186
|
+
if (i > 0)
|
|
187
|
+
await deps.sleep(intervalMs);
|
|
188
|
+
last = await deepOnce(expect.version);
|
|
189
|
+
if (last.ok)
|
|
190
|
+
return last;
|
|
191
|
+
}
|
|
192
|
+
return last;
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
async function deepOnce(expectedVersion) {
|
|
196
|
+
const token = await iapToken();
|
|
197
|
+
if (!token.ok)
|
|
198
|
+
return token;
|
|
199
|
+
const admin = await get(`${origins.admin}/_caelo/health?deep=1`, {
|
|
200
|
+
Authorization: `Bearer ${token.jwt}`,
|
|
201
|
+
});
|
|
202
|
+
if (!admin.reached)
|
|
203
|
+
return { ok: false, error: `admin unreachable: ${admin.error}` };
|
|
204
|
+
const a = evaluateAdminDeepHealth(admin.status, admin.text, expectedVersion);
|
|
205
|
+
if (!a.ok)
|
|
206
|
+
return a;
|
|
207
|
+
const gateway = await get(`${origins.gateway}/api/_caelo/health?deep=1`, {});
|
|
208
|
+
if (!gateway.reached)
|
|
209
|
+
return { ok: false, error: `gateway unreachable: ${gateway.error}` };
|
|
210
|
+
const g = evaluateGatewayDeepHealth(gateway.status, gateway.text, a.version);
|
|
211
|
+
return g.ok ? { ok: true, detail: `${a.detail}; ${g.detail}` } : g;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/upgrade/health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/** The two Caelo services shipped as release images. */
|
|
2
|
+
export type ReleaseService = "admin" | "gateway";
|
|
3
|
+
/** The services every install runs, in roll order (admin first, then gateway). */
|
|
4
|
+
export declare const RELEASE_SERVICES: readonly ReleaseService[];
|
|
5
|
+
/** GHCR — the canonical registry (release-images.yml), used by self-hosted Compose. */
|
|
6
|
+
export declare const GHCR_REGISTRY = "ghcr.io";
|
|
7
|
+
export declare const GHCR_NAMESPACE = "caelo-cms";
|
|
8
|
+
/** `ghcr.io/caelo-cms/<service>` — the repository of a service's release image. */
|
|
9
|
+
export declare function ghcrRepository(service: ReleaseService): string;
|
|
10
|
+
/** Where Caelo's release workflows live; every signer identity starts here. */
|
|
11
|
+
export declare const RELEASE_WORKFLOWS_URL = "https://github.com/caelo-cms/caelo-cms/.github/workflows";
|
|
12
|
+
/**
|
|
13
|
+
* The keyless signer cosign must see on every release image: one of the two
|
|
14
|
+
* release workflows of the caelo-cms repo, via GitHub's OIDC issuer. A
|
|
15
|
+
* different identity means a registry compromise, a typosquat, or a fork's
|
|
16
|
+
* image — every caller refuses to run it.
|
|
17
|
+
*/
|
|
18
|
+
export declare const RELEASE_SIGNER_IDENTITY_REGEXP = "https://github.com/caelo-cms/caelo-cms/.github/workflows/(release-images|release).yml@.*";
|
|
19
|
+
/** OIDC issuer of every Caelo release signature — images and release manifest (GitHub Actions). */
|
|
20
|
+
export declare const RELEASE_OIDC_ISSUER = "https://token.actions.githubusercontent.com";
|
|
21
|
+
/**
|
|
22
|
+
* The `cosign verify` argv for one image reference pinned by digest.
|
|
23
|
+
*
|
|
24
|
+
* @example cosignVerifyArgv("ghcr.io/caelo-cms/admin@sha256:…")
|
|
25
|
+
*/
|
|
26
|
+
export declare function cosignVerifyArgv(imageRef: string): string[];
|
|
27
|
+
/** A `sha256:<64 hex>` image / blob digest. */
|
|
28
|
+
export declare const IMAGE_DIGEST: RegExp;
|
|
29
|
+
/** Whether `s` is a well-formed `sha256:<64 hex>` digest. */
|
|
30
|
+
export declare function isImageDigest(s: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* `s` rebuilt character by character from a constant alphabet when it is a
|
|
33
|
+
* well-formed digest, else null. The digest comes from a registry's HTTP
|
|
34
|
+
* header and ends up in files (release.json, the Compose file); rebuilding
|
|
35
|
+
* it — rather than passing the checked string on — guarantees that nothing
|
|
36
|
+
* but `sha256:` and 64 hex digits from our own constants is ever written.
|
|
37
|
+
*/
|
|
38
|
+
export declare function canonicalDigest(s: string): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* A semver release tag (`v0.10.43`, `0.11.0-rc.1`) rebuilt from a constant
|
|
41
|
+
* alphabet, else null. The tag comes from the GitHub API and is recorded in
|
|
42
|
+
* release.json, so — like {@link canonicalDigest} — only our own characters
|
|
43
|
+
* reach the file.
|
|
44
|
+
*/
|
|
45
|
+
export declare function canonicalReleaseTag(s: string): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* The registry tag for an upgrade request: an explicit version (a leading
|
|
48
|
+
* `v` dropped, as release tags are `vX.Y.Z` but image tags `X.Y.Z`), else
|
|
49
|
+
* the channel's moving tag, else `latest`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function releaseTag(opts: {
|
|
52
|
+
readonly version?: string;
|
|
53
|
+
readonly channel?: "stable" | "rc" | "beta";
|
|
54
|
+
}): string;
|
|
55
|
+
export type DigestResult = {
|
|
56
|
+
ok: true;
|
|
57
|
+
digest: string;
|
|
58
|
+
} | {
|
|
59
|
+
ok: false;
|
|
60
|
+
reason: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Resolve `<registryHost>/<repository>:<tag>` to the digest a `docker pull`
|
|
64
|
+
* of that tag would fetch, through the Docker Registry V2 API anonymously.
|
|
65
|
+
*
|
|
66
|
+
* The images are public, but registries differ in how they say so: Artifact
|
|
67
|
+
* Registry answers the manifest HEAD directly, GHCR answers 401 with a
|
|
68
|
+
* `WWW-Authenticate: Bearer realm=…,service=…,scope=…` challenge whose realm
|
|
69
|
+
* hands out an anonymous pull token. Both paths are handled here, so callers
|
|
70
|
+
* never need registry credentials (end users have none for Caelo's).
|
|
71
|
+
*
|
|
72
|
+
* @param repository - path below the host, e.g. `caelo-cms/admin`.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveRegistryDigest(registryHost: string, repository: string, tag: string, fetchImpl?: typeof fetch): Promise<DigestResult>;
|
|
75
|
+
/**
|
|
76
|
+
* The key/value pairs of a `Bearer k="v",k2="v2"` challenge, or null when
|
|
77
|
+
* it is not a Bearer challenge.
|
|
78
|
+
*
|
|
79
|
+
* @example parseBearerChallenge('Bearer realm="https://ghcr.io/token",service="ghcr.io"')
|
|
80
|
+
* // → { realm: "https://ghcr.io/token", service: "ghcr.io" }
|
|
81
|
+
*/
|
|
82
|
+
export declare function parseBearerChallenge(header: string | null): Record<string, string> | null;
|
|
83
|
+
/**
|
|
84
|
+
* The tag of the newest stable Caelo release on GitHub (e.g. `v0.10.43`),
|
|
85
|
+
* or an error reason. Used to turn "upgrade to latest" into an exact
|
|
86
|
+
* version before anything is resolved, so the version an install records is
|
|
87
|
+
* a real release, never the moving `latest` tag.
|
|
88
|
+
*/
|
|
89
|
+
export declare function fetchLatestReleaseTag(fetchImpl?: typeof fetch): Promise<{
|
|
90
|
+
ok: true;
|
|
91
|
+
tag: string;
|
|
92
|
+
} | {
|
|
93
|
+
ok: false;
|
|
94
|
+
reason: string;
|
|
95
|
+
}>;
|
|
96
|
+
/** Where Caelo's release images live (public Artifact Registry repo). */
|
|
97
|
+
export declare const RELEASE_REGISTRY: {
|
|
98
|
+
readonly region: "europe-west1";
|
|
99
|
+
readonly project: "caelo-website";
|
|
100
|
+
readonly repo: "caelo-cms-images";
|
|
101
|
+
};
|
|
102
|
+
/** The digest-pinned reference of release image `slug@digest` in the Artifact Registry mirror. */
|
|
103
|
+
export declare function releaseImageRef(slug: string, digest: string): string;
|
|
104
|
+
/**
|
|
105
|
+
* Resolve a tag (e.g. `0.2.6` or `latest`) to its digest in the public
|
|
106
|
+
* Artifact Registry mirror, anonymously through the Registry V2 API
|
|
107
|
+
* ({@link resolveRegistryDigest}) — the caller's gcloud session needs no IAM
|
|
108
|
+
* access to the registry's project.
|
|
109
|
+
*/
|
|
110
|
+
export declare function resolveTagDigest(image: string, tag: string): Promise<DigestResult>;
|
|
111
|
+
/**
|
|
112
|
+
* P21 ship 4 — verify cosign keyless signatures on every planned
|
|
113
|
+
* image digest. Sigstore Fulcio + Rekor; the certificate identity
|
|
114
|
+
* must match the Caelo release-images workflow. A mismatch means
|
|
115
|
+
* either a registry compromise, a typosquat, or the operator pointed
|
|
116
|
+
* at a fork's image. Either way: refuse to roll.
|
|
117
|
+
*
|
|
118
|
+
* Returns true on success (or skips with a clear error and returns
|
|
119
|
+
* false if cosign isn't installed / verification fails).
|
|
120
|
+
*/
|
|
121
|
+
export declare function verifyCosignAll(plans: readonly {
|
|
122
|
+
readonly slug: string;
|
|
123
|
+
readonly digest: string;
|
|
124
|
+
}[]): Promise<boolean>;
|
|
125
|
+
//# sourceMappingURL=release-images.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-images.d.ts","sourceRoot":"","sources":["../../src/upgrade/release-images.ts"],"names":[],"mappings":"AAkBA,wDAAwD;AACxD,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,CAAC;AAEjD,kFAAkF;AAClF,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAAyB,CAAC;AAEhF,uFAAuF;AACvF,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,cAAc,cAAc,CAAC;AAE1C,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAE9D;AAED,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,6DAA6D,CAAC;AAEhG;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,6FAA6D,CAAC;AAEzG,mGAAmG;AACnG,eAAO,MAAM,mBAAmB,gDAAgD,CAAC;AAEjF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAU3D;AAED,+CAA+C;AAC/C,eAAO,MAAM,YAAY,QAA0B,CAAC;AAEpD,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEhD;AAID;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIxD;AAKD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG5D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,MAAM,CAAC;CAC7C,GAAG,MAAM,CAKT;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAUxF;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,YAAY,CAAC,CAsBvB;AAwBD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAQzF;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAepE;AAED,yEAAyE;AACzE,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAEX,kGAAkG;AAClG,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAGlF;AA2DD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,GACnE,OAAO,CAAC,OAAO,CAAC,CA+BlB"}
|