Merge PR #403: scoped DEV CD rollout verification

Allow authorized DEV CD rollout runs to skip M3/durable postflight while still publishing/applying and verifying 16666/16667 health.
This commit is contained in:
Lyon
2026-05-24 07:12:19 +08:00
committed by GitHub
2 changed files with 61 additions and 17 deletions
+26 -17
View File
@@ -84,6 +84,7 @@ export function parseArgs(argv) {
ownerTaskId: null,
breakStaleLock: false,
skipLiveVerify: false,
skipRuntimePostflight: false,
status: false,
dryRun: false,
fullOutput: false,
@@ -118,6 +119,9 @@ export function parseArgs(argv) {
} else if (arg === "--skip-live-verify") {
args.skipLiveVerify = true;
args.flags.add(arg);
} else if (arg === "--skip-runtime-postflight") {
args.skipRuntimePostflight = true;
args.flags.add(arg);
} else if (arg === "--report") {
args.reportPath = readOption(argv, ++index, arg);
args.flags.add(arg);
@@ -194,6 +198,7 @@ export function usage() {
"--report PATH": `default: ${defaultReportPath}`,
"--write-report": "Write the full report to --report.",
"--full-output": "Print the full report to stdout instead of the concise summary.",
"--skip-runtime-postflight": "Skip the M3/durable runtime postflight while still applying DEV and verifying 16666/16667 health.",
"--skip-live-verify": "test-only escape hatch; do not use for DEV acceptance"
}
};
@@ -2718,23 +2723,27 @@ export async function runDevCdApply(argv, io = {}) {
timeoutMs: 20 * 60 * 1000,
reportPath: "reports/dev-gate/dev-deploy-report.json"
},
{
id: "runtime-durable-postflight",
phase: "verifying",
command: process.execPath,
args: [
"scripts/dev-runtime-postflight.mjs",
"--live",
"--confirm-dev",
"--confirmed-non-production",
"--target",
"api",
"--write-report",
"--fail-on-blocked"
],
timeoutMs: 2 * 60 * 1000,
reportPath: runtimePostflightReportPath
}
...(
args.skipRuntimePostflight
? []
: [{
id: "runtime-durable-postflight",
phase: "verifying",
command: process.execPath,
args: [
"scripts/dev-runtime-postflight.mjs",
"--live",
"--confirm-dev",
"--confirmed-non-production",
"--target",
"api",
"--write-report",
"--fail-on-blocked"
],
timeoutMs: 2 * 60 * 1000,
reportPath: runtimePostflightReportPath
}]
)
];
if (blockers.length === 0) {
+35
View File
@@ -1313,6 +1313,41 @@ test("transaction runs phases, allows internal side-effect env, releases lock, a
assert.equal(writtenReport.devCdApply.liveVerify.summary.checked, 2);
});
test("transaction can skip runtime postflight while preserving publish apply and live verify", async () => {
const repoRoot = await makeRepo();
const commandLog = [];
let output = "";
const code = await runDevCdApply([
"--apply",
"--confirm-dev",
"--confirmed-non-production",
"--owner-task-id",
"task-skip-postflight",
"--kubeconfig",
"/etc/rancher/k3s/k3s.yaml",
"--write-report",
"--full-output",
"--skip-runtime-postflight"
], {
repoRoot,
env: {},
runCommand: makeRunCommand({ commandLog }),
httpGetJson: makeHttpGetJson(),
now: () => new Date(iso(100000)),
stdout: { write: (chunk) => { output += chunk; } }
});
const report = JSON.parse(output);
assert.equal(code, 0);
assert.equal(report.status, "pass");
assert.equal(report.devCdApply.steps.some((step) => step.id === "artifact-publish"), true);
assert.equal(report.devCdApply.steps.some((step) => step.id === "dev-deploy-apply"), true);
assert.equal(report.devCdApply.steps.some((step) => step.id === "runtime-durable-postflight"), false);
assert.equal(commandLog.some((entry) => entry.args.includes("scripts/dev-runtime-postflight.mjs")), false);
assert.equal(report.devCdApply.liveVerify.status, "pass");
assert.equal(report.devCdApply.liveVerify.summary.checked, 2);
});
test("transaction blocks with structured runtime postflight blocker when M3 evidence is not persisted", async () => {
const repoRoot = await makeRepo();
const commandLog = [];