everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
113 lines (111 loc) • 3.84 kB
JavaScript
const require_types = require('../../types.cjs');
const require_services_registry_fastkv = require('../registry/fastkv.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 payload = require_rollback.buildRollbackPayload(require_types.BosConfigSchema.parse(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
});
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
exports.fetchLiveConfig = fetchLiveConfig;
exports.fetchRollbackHistory = fetchRollbackHistory;
exports.isSnapshotLive = isSnapshotLive;
exports.publishRollbackSnapshot = publishRollbackSnapshot;
exports.rollbackToPreviousSnapshot = rollbackToPreviousSnapshot;
//# sourceMappingURL=rollback-flow.cjs.map