UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

153 lines (151 loc) • 5.65 kB
const require_services_registry_fastkv = require('../registry/fastkv.cjs'); const require_manifest = require('../platform/manifest.cjs'); const require_boot_check = require('../resolution/boot-check.cjs'); const require_rollback = require('./rollback.cjs'); const require_train = require('./train.cjs'); //#region src/services/deploy/rollback-flow.ts async function fetchRollbackHistory(input) { return require_services_registry_fastkv.fetchConfigHistory({ accountId: input.account, gatewayId: input.domain, registry: input.registry, limit: input.limit }); } /** The live config, or undefined when the registry read fails (an unknown * live state never blocks a rollback — the snapshot publish is idempotent). */ async function fetchLiveConfig(input) { try { return await require_services_registry_fastkv.fetchBosConfigFromFastKv(`bos://${input.account}/${input.domain}`, input.registry); } catch { return; } } function isSnapshotLive(targetValue, liveValue) { return JSON.stringify(liveValue) === JSON.stringify(targetValue); } /** Stamp + republish the target snapshot verbatim. Callers own verification: * the smoke protocol refuses unverified targets via * `rollbackToPreviousSnapshot`; the command runs its two-stage check and * passes `skipVerify` once it has vetted (or --forced) the snapshot. */ async function publishRollbackSnapshot(targetValue, input, opts) { if (!opts?.skipVerify) { const verification = await require_rollback.verifyRollbackSnapshot(targetValue); if (!verification.ok && verification.verifiable) return { ok: false, registryUrl: "", error: "rollback refused — a pinned slot's bytes are gone or no longer match their SRI" }; } const bootCheck = await require_boot_check.verifyBootPayload(targetValue, { account: input.account, gateway: input.domain }, { ...input.registry ? { registry: input.registry } : {} }); if (!bootCheck.ok) { const detail = bootCheck.issues.map((issue) => `${issue.path ? `${issue.path}: ` : ""}${issue.message}`).join("; "); return { ok: false, registryUrl: "", error: `rollback refused — the target snapshot would not boot${bootCheck.chain.length > 0 ? ` (extends chain: ${bootCheck.chain.join(" -> ")})` : ""}: ${detail}` }; } const payload = require_rollback.buildRollbackPayload(targetValue, (/* @__PURE__ */ new Date()).toISOString()); const result = await require_train.publishToFastKv({ bosConfig: payload, runtimeConfig: input.runtimeConfig, configDir: input.configDir, env: input.env, build: false, dryRun: input.dryRun ?? false, verbose: input.verbose ?? false, packages: "all", network: input.network, privateKey: input.privateKey, wallet: input.wallet ?? false, registry: input.registry, exactPayload: true, ...opts?.restorePlatformPointer ? { restorePlatformPointer: opts.restorePlatformPointer } : {} }); if (result.status === "dry-run") return { ok: true, registryUrl: result.registryUrl, dryRun: true }; if (result.status === "error") return { ok: false, registryUrl: result.registryUrl, error: `rollback publish failed: ${result.error ?? result.status}` }; return { ok: true, registryUrl: result.registryUrl, txHash: result.txHash }; } /** The platform-pointer restore for a rollback (#573): the pointer's own * history[1] is the pre-release manifest — the same "previous entry" logic * the config rollback uses. Best-effort: a failed lookup returns undefined * and the drift alarm (#571's cross-check) catches any residue loudly. */ async function resolvePointerRestore(account, domain, registry) { try { const previousPointer = (await require_services_registry_fastkv.fetchConfigHistory({ accountId: account, gatewayId: domain, registry, limit: 5, keyPath: "platform.json" }))[1]; if (!previousPointer) return void 0; return { key: require_manifest.getPlatformManifestKey(account, domain), value: JSON.stringify(previousPointer.value) }; } catch { console.warn(" platform pointer restore unavailable — the drift alarm will catch any residue"); return; } } /** The post-publish smoke failure protocol (ADR 0021): roll the registry * config back to the previous snapshot — a red boot gate must never leave a * new config live against an old image. #573: the platform pointer rolls * back in the same atomic write. */ async function rollbackToPreviousSnapshot(input) { let history; try { history = await fetchRollbackHistory({ account: input.account, domain: input.domain, registry: input.registry, limit: 20 }); } catch (error) { return { ok: false, registryUrl: "", error: `fetching publish history failed: ${error instanceof Error ? error.message : String(error)}` }; } const previous = history[1]; if (!previous) return { ok: false, registryUrl: "", error: "no previous snapshot in the publish history — nothing to roll back to" }; const restorePlatformPointer = await resolvePointerRestore(input.account, input.domain, input.registry); const result = await publishRollbackSnapshot(previous.value, input, { restorePlatformPointer }); if (result.ok) return { ok: true, blockHeight: String(previous.blockHeight), registryUrl: result.registryUrl, txHash: result.txHash }; return result; } //#endregion exports.fetchLiveConfig = fetchLiveConfig; exports.fetchRollbackHistory = fetchRollbackHistory; exports.isSnapshotLive = isSnapshotLive; exports.publishRollbackSnapshot = publishRollbackSnapshot; exports.resolvePointerRestore = resolvePointerRestore; exports.rollbackToPreviousSnapshot = rollbackToPreviousSnapshot; //# sourceMappingURL=rollback-flow.cjs.map