From 2e41cba31dee3a7b1f54fb7fed4ff081bb30593e Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 24 May 2026 06:40:07 +0000 Subject: [PATCH] fix: treat dev cd artifact audits as non-blocking --- scripts/src/dev-cd-apply.mjs | 30 ++++++++++++----- scripts/src/dev-cd-apply.test.mjs | 56 +++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/scripts/src/dev-cd-apply.mjs b/scripts/src/dev-cd-apply.mjs index c72d3509..070ae11e 100644 --- a/scripts/src/dev-cd-apply.mjs +++ b/scripts/src/dev-cd-apply.mjs @@ -730,6 +730,19 @@ function validateArgs(args) { } } +function artifactBoundaryRequiresApplyBlock(target) { + if (target.publishRequired !== false) return false; + if (target.artifactBoundary?.status !== "degraded") return false; + + const desiredState = target.artifactBoundary.desiredState ?? {}; + const desiredStateCheckPass = target.desiredStateCheck?.status === "pass"; + const releaseGatePinsMatch = + desiredState.deployCommitMatches === true && + desiredState.catalogCommitMatches === true; + + return !(desiredStateCheckPass && releaseGatePinsMatch); +} + function lockAnnotationValue(value) { if (value === undefined || value === null) return ""; if (typeof value === "string") return value; @@ -2534,22 +2547,23 @@ export async function runDevCdApply(argv, io = {}) { const artifactEvidence = await readArtifactEvidence(ctx.repoRoot); target = await resolveEffectiveTarget(ctx, args, deployBefore, artifactEvidence); if (target.desiredStateCheck?.status === "blocked") { + blockers.push({ + type: "contract_blocker", + scope: "desired-state-promotion", + status: "open", + summary: "deploy/deploy.json is not aligned with the target ref, and the deploy-json promotion check did not pass." + }); throw new DevCdApplyError("deploy desired-state does not match the target ref or a published deploy.json promotion", { code: "desired-state-promotion-check-failed", - blockers: [{ - type: "contract_blocker", - scope: "desired-state-promotion", - status: "open", - summary: "deploy/deploy.json is not aligned with the target ref, and the deploy-json promotion check did not pass." - }] + suppressCatchBlocker: true }); } - if (target.publishRequired === false && target.artifactBoundary?.status === "degraded") { + if (artifactBoundaryRequiresApplyBlock(target)) { blockers.push({ type: "contract_blocker", scope: "artifact-boundary", status: "open", - summary: "deploy/deploy.json, deploy/artifact-catalog.dev.json, deploy/k8s/base/workloads.yaml, and the artifact merge parent must resolve to the same promotion commit before apply." + summary: "deploy/deploy.json, deploy/artifact-catalog.dev.json, deploy/k8s/base/workloads.yaml, and registry manifests must prove the same promotion commit before apply." }); throw new DevCdApplyError("artifact desired-state provenance does not match the deploy.json promotion", { code: "artifact-boundary-provenance-mismatch", diff --git a/scripts/src/dev-cd-apply.test.mjs b/scripts/src/dev-cd-apply.test.mjs index fe1cdcc0..1f926f0a 100644 --- a/scripts/src/dev-cd-apply.test.mjs +++ b/scripts/src/dev-cd-apply.test.mjs @@ -762,7 +762,7 @@ test("dev-cd status degrades artifact merge provenance when catalog does not mat assertNoReadOnlySideEffects(commandLog); }); -test("apply stops before lock acquisition when artifact merge provenance mismatches deploy-json promotion", async () => { +test("apply treats artifact audit mismatch as non-blocking when deploy-json promotion desired state passes", async () => { const repoRoot = await makeRepo({ commitId: "abc1234" }); await writeFile( artifactReportFixturePath, @@ -788,7 +788,8 @@ test("apply stops before lock acquisition when artifact merge provenance mismatc "--owner-task-id", "task-provenance", "--kubeconfig", - "/etc/rancher/k3s/k3s.yaml" + "/etc/rancher/k3s/k3s.yaml", + "--full-output" ], { repoRoot, env: {}, @@ -810,10 +811,59 @@ test("apply stops before lock acquisition when artifact merge provenance mismatc stdout: { write: (chunk) => { output += chunk; } } }); + const summary = JSON.parse(output); + assert.equal(code, 0); + assert.equal(summary.status, "pass"); + assert.equal(summary.devCdApply.target.promotionSource, "deploy-json"); + assert.equal(summary.devCdApply.target.publishRequired, false); + assert.equal(summary.devCdApply.target.desiredStateCheck.status, "pass"); + assert.equal(summary.devCdApply.target.artifactBoundary.status, "degraded"); + assert.equal(summary.devCdApply.target.artifactBoundary.reportStatus, "stale_or_unrelated"); + assert.equal(summary.devCdApply.target.artifactBoundary.reportIsReleaseGate, false); + assert.equal(commandLog.some((entry) => entry.args.includes("scripts/dev-artifact-publish.mjs")), false); + assert.equal(commandLog.some((entry) => entry.args.includes("scripts/refresh-artifact-catalog.mjs")), false); + assert.equal(commandLog.some((entry) => entry.args.includes("scripts/deploy-desired-state-plan.mjs")), true); + assert.equal(commandLog.some((entry) => entry.args.includes("scripts/dev-deploy-apply.mjs")), true); +}); + +test("apply stops before lock acquisition when deploy-json promotion desired-state check fails", async () => { + const repoRoot = await makeRepo({ commitId: "abc1234" }); + const commandLog = []; + let output = ""; + const code = await runDevCdApply([ + "--apply", + "--confirm-dev", + "--confirmed-non-production", + "--owner-task-id", + "task-promotion-check-failed", + "--kubeconfig", + "/etc/rancher/k3s/k3s.yaml" + ], { + repoRoot, + env: {}, + runCommand: makeRunCommand({ + commandLog, + targetCommitId: laterControlCommit, + headCommitId: laterControlCommit, + extraGitRefs: { + abc1234: publishedCommit + }, + desiredStatePromotionStatus: "blocked", + latestArtifactMergeCommit: artifactMergeCommit, + commitParents: { + [artifactMergeCommit]: [laterControlCommit, artifactReportCommit], + [artifactReportCommit]: [laterControlCommit] + } + }), + httpGetJson: makeHttpGetJson(), + now: () => new Date(iso(100000)), + stdout: { write: (chunk) => { output += chunk; } } + }); + const summary = JSON.parse(output); assert.equal(code, 2); assert.equal(summary.status, "blocked"); - assert.equal(summary.blockers.some((blocker) => blocker.scope === "artifact-boundary"), true); + assert.equal(summary.blockers.some((blocker) => blocker.scope === "desired-state-promotion"), true); assert.equal(commandLog.some((entry) => entry.command.includes("kubectl")), false); assert.equal(commandLog.some((entry) => entry.args.includes("scripts/dev-artifact-publish.mjs")), false); assert.equal(commandLog.some((entry) => entry.args.includes("scripts/dev-deploy-apply.mjs")), false);