From cb218b61b4cf63791355e79cec76ab3f3aad8df6 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 14 Jul 2026 00:33:33 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AF=B9=E9=BD=90=20runtime=20GitOps=20?= =?UTF-8?q?verify=20terminal=20=E5=90=88=E5=90=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/native/cicd/pac-status-evaluator.cjs | 91 ++++++++++++++++++-- 1 file changed, 86 insertions(+), 5 deletions(-) diff --git a/scripts/native/cicd/pac-status-evaluator.cjs b/scripts/native/cicd/pac-status-evaluator.cjs index f60a62c3..30454536 100644 --- a/scripts/native/cicd/pac-status-evaluator.cjs +++ b/scripts/native/cicd/pac-status-evaluator.cjs @@ -25,6 +25,12 @@ function exactSkipMarker(records, event) { && item.reason === "no-build-no-rollout-plan") || null; } +function exactRuntimeGitopsVerifyMarker(records) { + return [...records].reverse().find((item) => item.event === "gitops-promote" + && item.status === "continuing" + && item.reason === "no-build-no-rollout-plan-gitops-verify") || null; +} + const pacContractTasks = new Set(["plan-artifacts", "collect-artifacts", "gitops-promote"]); function firstString(...values) { @@ -365,10 +371,11 @@ function extractPacSourceObservation(recordsInput) { const plan = [...records].reverse().find((item) => item.event === "pac-delivery-plan" || item.event === "g14-ci-plan") || null; const collectMarker = exactSkipMarker(records, "collect-artifacts"); const promoteMarker = exactSkipMarker(records, "gitops-promote"); + const runtimeGitopsVerifyMarker = exactRuntimeGitopsVerifyMarker(records); const planTask = exactTaskTerminal(records, "plan-artifacts"); const collectTask = exactTaskTerminal(records, "collect-artifacts"); const promoteTask = exactTaskTerminal(records, "gitops-promote"); - if (plan === null && collectMarker === null && promoteMarker === null && planTask === null && collectTask === null && promoteTask === null) return null; + if (plan === null && collectMarker === null && promoteMarker === null && runtimeGitopsVerifyMarker === null && planTask === null && collectTask === null && promoteTask === null) return null; const affected = stringArray(plan?.affectedServices); const rollout = stringArray(plan?.rolloutServices); @@ -384,6 +391,8 @@ function extractPacSourceObservation(recordsInput) { const noRuntimeChangeMarkers = collectMarker !== null && promoteMarker !== null; const skipMarkerSeen = collectMarker !== null || promoteMarker !== null; const skipMarkerConflict = skipMarkerSeen && !noRuntimeChangePlan; + const runtimeGitopsVerifyMarkerConflict = runtimeGitopsVerifyMarker !== null + && (!noRuntimeChangePlan || skipMarkerSeen); const deliveryTerminalReady = planTask?.status === "succeeded" && collectTask?.status === "succeeded" && promoteTask?.status === "succeeded"; @@ -394,10 +403,14 @@ function extractPacSourceObservation(recordsInput) { let mode = "inconsistent"; let valid = false; let reason = "structured-plan-or-terminal-marker-is-incomplete"; - if (planShapeValid && sourceCommitValid && noRuntimeChangePlan && noRuntimeChangeMarkers) { + if (planShapeValid && sourceCommitValid && noRuntimeChangePlan && noRuntimeChangeMarkers && runtimeGitopsVerifyMarker === null) { mode = "no-runtime-change"; valid = true; reason = "no-build-no-rollout-plan"; + } else if (planShapeValid && sourceCommitValid && noRuntimeChangePlan && runtimeGitopsVerifyMarker !== null && !runtimeGitopsVerifyMarkerConflict && deliveryTerminalReady) { + mode = "runtime-gitops-verify"; + valid = true; + reason = "no-build-no-rollout-plan-gitops-verify"; } else if (planShapeValid && sourceCommitValid && !noRuntimeChangePlan && !skipMarkerConflict && deliveryTerminalReady) { mode = "delivery"; valid = true; @@ -406,10 +419,14 @@ function extractPacSourceObservation(recordsInput) { reason = "source-commit-invalid-or-missing"; } else if (!planShapeValid) { reason = "delivery-plan-shape-invalid-or-missing"; + } else if (runtimeGitopsVerifyMarkerConflict) { + reason = "runtime-gitops-verify-marker-conflicts-with-plan-or-skip-marker"; } else if (skipMarkerConflict) { reason = "no-runtime-change-marker-conflicts-with-delivery-plan"; } else if (deliveryTerminalFailed) { reason = "delivery-terminal-failed"; + } else if (noRuntimeChangePlan && runtimeGitopsVerifyMarker !== null) { + reason = "runtime-gitops-verify-terminal-evidence-incomplete"; } else if (!noRuntimeChangePlan) { reason = "delivery-terminal-evidence-incomplete"; } @@ -440,7 +457,9 @@ function extractPacSourceObservation(recordsInput) { terminalSources: { planArtifacts: terminalSource(planTask, plan, "observed", planMarkerSource), collectArtifacts: terminalSource(collectTask, collectMarker), - gitopsPromote: terminalSource(promoteTask, promoteMarker), + gitopsPromote: runtimeGitopsVerifyMarker === null + ? terminalSource(promoteTask, promoteMarker) + : terminalSource(promoteTask, runtimeGitopsVerifyMarker, "continuing", "runtime-gitops-verify-structured-log"), }, valuesPrinted: false, }; @@ -602,14 +621,14 @@ function evaluatePacStatus(inputValue) { const deliveryDisabled = artifact.imageStatus === "disabled"; const deliverySkipped = artifact.imageStatus === "skipped"; const sourceObservationMode = stringOrNull(sourceObservation.mode); - const hwlabCatalogDelivery = sourceObservationMode === "delivery" + const hwlabCatalogDelivery = (sourceObservationMode === "delivery" || sourceObservationMode === "runtime-gitops-verify") && sourceObservation.contract === "hwlab-g14-ci-plan"; const noRuntimeChange = sourceObservationMode === "no-runtime-change"; const catalog = record(artifact.catalog); const catalogPresent = catalog.present === true; const catalogSourceCommit = stringOrNull(catalog.sourceCommit); const catalogSourceMatches = catalogSourceCommit !== null && catalogSourceCommit === sourceCommit; - const catalogDeliveryEvidence = sourceObservationMode === "delivery" + const catalogDeliveryEvidence = (sourceObservationMode === "delivery" || sourceObservationMode === "runtime-gitops-verify") && sourceObservation.valid === true && catalogPresent && catalog.status === "published" @@ -892,6 +911,24 @@ function deliveryObservation(sourceCommit = "c".repeat(40)) { ]); } +function runtimeGitopsVerifyObservation(sourceCommit = "c".repeat(40)) { + return extractPacSourceObservation([ + { + event: "g14-ci-plan", + sourceCommitId: sourceCommit, + affectedServices: [], + rolloutServices: [], + buildServices: [], + reusedServices: Array.from({ length: 8 }, (_item, index) => `service-${index}`), + noImageBuildReason: "test-only-change", + }, + { event: "gitops-promote", status: "continuing", reason: "no-build-no-rollout-plan-gitops-verify" }, + { event: "pac-task-terminal", pipelineTask: "plan-artifacts", taskRun: "plan", status: "succeeded", reason: "Succeeded", results: [] }, + { event: "pac-task-terminal", pipelineTask: "collect-artifacts", taskRun: "collect", status: "succeeded", reason: "Succeeded", results: [] }, + { event: "pac-task-terminal", pipelineTask: "gitops-promote", taskRun: "promote", status: "succeeded", reason: "Succeeded", results: [] }, + ]); +} + function publishedCatalog(sourceCommit = "c".repeat(40)) { return { present: true, status: "published", sourceCommit, registryVerified: true }; } @@ -902,6 +939,7 @@ function runPacStatusFixtureChecks() { const revision = "b".repeat(40); const retained = noRuntimeChangeObservation(); const delivery = deliveryObservation(); + const runtimeGitopsVerify = runtimeGitopsVerifyObservation(); const exactArgo = { sync: "Synced", health: "Healthy", revision, revisionRelation: { relation: "exact", expectedRevision: revision, observedRevision: revision } }; const cases = [ { @@ -910,6 +948,24 @@ function runPacStatusFixtureChecks() { expectedCode: "pac-ready-no-runtime-change", input: fixtureInput({ artifact: { imageStatus: "retained", sourceObservation: retained } }), }, + { + id: "runtime-gitops-verify-ready", + expectedOk: true, + expectedCode: "pac-ready-gitops-exact", + input: fixtureInput({ artifact: { imageStatus: "reused", digest: digestA, digests: [digestA], gitopsCommit: revision, sourceObservation: runtimeGitopsVerify, catalog: publishedCatalog() }, argo: exactArgo }), + }, + { + id: "runtime-gitops-verify-catalog-missing", + expectedOk: false, + expectedCode: "pac-artifact-catalog-missing", + input: fixtureInput({ artifact: { imageStatus: "reused", digest: digestA, digests: [digestA], gitopsCommit: revision, sourceObservation: runtimeGitopsVerify }, argo: exactArgo }), + }, + { + id: "runtime-gitops-verify-gitops-missing", + expectedOk: false, + expectedCode: "pac-gitops-missing", + input: fixtureInput({ artifact: { imageStatus: "reused", digest: digestA, digests: [digestA], sourceObservation: runtimeGitopsVerify, catalog: publishedCatalog() }, argo: exactArgo }), + }, { id: "retained-gitops-missing", expectedOk: false, @@ -1000,6 +1056,31 @@ function runPacStatusFixtureChecks() { expectedCode: "pac-source-observation-inconsistent", input: fixtureInput({ artifact: { sourceObservation: extractPacSourceObservation([{ event: "g14-ci-plan", sourceCommitId: "c".repeat(40), affectedServices: [], rolloutServices: [], buildServices: [], reusedServices: [] }]) } }), }, + { + id: "runtime-gitops-verify-marker-missing", + expectedOk: false, + expectedCode: "pac-source-observation-inconsistent", + input: fixtureInput({ artifact: { sourceObservation: extractPacSourceObservation([ + { event: "g14-ci-plan", sourceCommitId: "c".repeat(40), affectedServices: [], rolloutServices: [], buildServices: [], reusedServices: ["service"] }, + { event: "pac-task-terminal", pipelineTask: "plan-artifacts", taskRun: "plan", status: "succeeded", reason: "Succeeded", results: [] }, + { event: "pac-task-terminal", pipelineTask: "collect-artifacts", taskRun: "collect", status: "succeeded", reason: "Succeeded", results: [] }, + { event: "pac-task-terminal", pipelineTask: "gitops-promote", taskRun: "promote", status: "succeeded", reason: "Succeeded", results: [] }, + ]) } }), + }, + { + id: "runtime-gitops-verify-marker-conflict", + expectedOk: false, + expectedCode: "pac-source-observation-inconsistent", + input: fixtureInput({ artifact: { sourceObservation: extractPacSourceObservation([ + { event: "g14-ci-plan", sourceCommitId: "c".repeat(40), affectedServices: [], rolloutServices: [], buildServices: [], reusedServices: ["service"] }, + { event: "collect-artifacts", status: "skipped", reason: "no-build-no-rollout-plan" }, + { event: "gitops-promote", status: "skipped", reason: "no-build-no-rollout-plan" }, + { event: "gitops-promote", status: "continuing", reason: "no-build-no-rollout-plan-gitops-verify" }, + { event: "pac-task-terminal", pipelineTask: "plan-artifacts", taskRun: "plan", status: "succeeded", reason: "Succeeded", results: [] }, + { event: "pac-task-terminal", pipelineTask: "collect-artifacts", taskRun: "collect", status: "succeeded", reason: "Succeeded", results: [] }, + { event: "pac-task-terminal", pipelineTask: "gitops-promote", taskRun: "promote", status: "succeeded", reason: "Succeeded", results: [] }, + ]) } }), + }, { id: "retained-source-mismatch", expectedOk: false,