UNPKG

everything-dev

Version:

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

109 lines (107 loc) • 3.61 kB
import { BosConfigSchema } from "../../types.mjs"; import { fetchBosConfigFromFastKv, fetchConfigHistory } from "../registry/fastkv.mjs"; import { buildRollbackPayload, verifyRollbackSnapshot } from "./rollback.mjs"; import { publishToFastKv } from "./train.mjs"; //#region src/services/deploy/rollback-flow.ts async function fetchRollbackHistory(input) { return 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 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 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 payload = buildRollbackPayload(BosConfigSchema.parse(targetValue), (/* @__PURE__ */ new Date()).toISOString()); const result = await 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 }); 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 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. */ 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 result = await publishRollbackSnapshot(previous.value, input); if (result.ok) return { ok: true, blockHeight: String(previous.blockHeight), registryUrl: result.registryUrl, txHash: result.txHash }; return result; } //#endregion export { fetchLiveConfig, fetchRollbackHistory, isSnapshotLive, publishRollbackSnapshot, rollbackToPreviousSnapshot }; //# sourceMappingURL=rollback-flow.mjs.map