"use strict"; function record(value) { return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {}; } function stringOrNull(value) { return typeof value === "string" && value.length > 0 ? value : null; } function stringArray(value) { return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : null; } function digestFromImage(value) { if (typeof value !== "string" || !value.includes("@")) return null; return value.split("@").slice(1).join("@") || null; } function exactSkipMarker(records, event) { return [...records].reverse().find((item) => item.event === event && item.status === "skipped" && item.reason === "no-build-no-rollout-plan") || null; } function extractPacSourceObservation(recordsInput) { const records = Array.isArray(recordsInput) ? recordsInput.map(record) : []; const plan = [...records].reverse().find((item) => item.event === "g14-ci-plan") || null; const collectMarker = exactSkipMarker(records, "collect-artifacts"); const promoteMarker = exactSkipMarker(records, "gitops-promote"); if (plan === null && collectMarker === null && promoteMarker === null) return null; const affected = stringArray(plan?.affectedServices); const rollout = stringArray(plan?.rolloutServices); const build = stringArray(plan?.buildServices); const reused = stringArray(plan?.reusedServices); const sourceCommit = stringOrNull(plan?.sourceCommitId); const planShapeValid = affected !== null && rollout !== null && build !== null; const sourceCommitValid = sourceCommit !== null && /^[0-9a-f]{40}$/iu.test(sourceCommit); const noRuntimeChangePlan = planShapeValid && affected.length === 0 && rollout.length === 0 && build.length === 0; const noRuntimeChangeMarkers = collectMarker !== null && promoteMarker !== null; const skipMarkerSeen = collectMarker !== null || promoteMarker !== null; const skipMarkerConflict = skipMarkerSeen && !noRuntimeChangePlan; let mode = "inconsistent"; let valid = false; let reason = "structured-plan-or-terminal-marker-is-incomplete"; if (planShapeValid && sourceCommitValid && noRuntimeChangePlan && noRuntimeChangeMarkers) { mode = "no-runtime-change"; valid = true; reason = "no-build-no-rollout-plan"; } else if (planShapeValid && sourceCommitValid && !noRuntimeChangePlan && !skipMarkerConflict) { mode = "delivery"; valid = true; reason = "artifact-or-runtime-delivery-required"; } else if (!sourceCommitValid) { reason = "source-commit-invalid-or-missing"; } else if (!planShapeValid) { reason = "delivery-plan-shape-invalid-or-missing"; } else if (skipMarkerConflict) { reason = "no-runtime-change-marker-conflicts-with-delivery-plan"; } return { schemaVersion: "v1", contract: "hwlab-g14-ci-plan", mode, valid, reason, sourceCommit, plan: { affectedServiceCount: affected?.length ?? null, rolloutServiceCount: rollout?.length ?? null, buildServiceCount: build?.length ?? null, reusedServiceCount: reused?.length ?? null, }, terminal: { collectArtifacts: collectMarker === null ? "missing" : "no-build-no-rollout-plan", gitopsPromote: promoteMarker === null ? "missing" : "no-build-no-rollout-plan", }, valuesPrinted: false, }; } function evaluatePacStatus(inputValue) { const input = record(inputValue); const artifact = record(input.artifact); const argo = record(input.argo); const runtime = record(input.runtime); const sourceObservation = record(artifact.sourceObservation); const revisionRelation = record(argo.revisionRelation); const gitopsRelation = stringOrNull(revisionRelation.relation) || "unknown"; const sourceCommit = stringOrNull(input.sourceCommit); const registryDigest = stringOrNull(input.registryDigest); const artifactDigest = stringOrNull(artifact.digest); const expectedDigest = registryDigest || artifactDigest; const runtimeImage = stringOrNull(runtime.image); const runtimeDigest = stringOrNull(runtime.digest) || digestFromImage(runtimeImage); const runtimeMatches = expectedDigest === null || runtimeDigest === expectedDigest; const runtimeReady = Number.isInteger(runtime.replicas) && runtime.replicas > 0 && runtime.readyReplicas === runtime.replicas; const selectedArtifactDigests = [...new Set([ artifactDigest, ...(Array.isArray(artifact.digests) ? artifact.digests : []), ].filter((value) => typeof value === "string" && value.length > 0))]; const selectedArtifactMatchesRuntime = runtimeDigest !== null && selectedArtifactDigests.includes(runtimeDigest); const registryMatchesArtifact = registryDigest === null || artifactDigest === null || registryDigest === artifactDigest; const healthUrl = stringOrNull(input.healthUrl); const healthStatus = stringOrNull(input.healthStatus); const healthReady = healthUrl === null || healthStatus === "200"; const gitopsReady = stringOrNull(artifact.gitopsCommit) !== null && stringOrNull(argo.revision) !== null; const gitopsRevisionAligned = gitopsRelation === "exact" || gitopsRelation === "descendant"; const deliveryDisabled = artifact.imageStatus === "disabled"; const deliverySkipped = artifact.imageStatus === "skipped"; const sourceObservationMode = stringOrNull(sourceObservation.mode); const noRuntimeChange = sourceObservationMode === "no-runtime-change"; const sourceObservationInconsistent = sourceObservationMode === "inconsistent" || (sourceObservationMode !== null && sourceObservation.valid !== true); const observationSourceCommit = stringOrNull(sourceObservation.sourceCommit); const observationSourceMatches = sourceCommit !== null && observationSourceCommit === sourceCommit; const retainedRevision = stringOrNull(argo.revision); const retainedDigestReady = runtimeDigest !== null && /^sha256:[0-9a-f]{64}$/iu.test(runtimeDigest); const retainedOutputConflict = noRuntimeChange && (stringOrNull(artifact.gitopsCommit) !== null || artifactDigest !== null || selectedArtifactDigests.length > 0); let code = "pac-diagnostics-not-applicable"; let phase = "not-applicable"; let ok = true; let hint = "consumer did not expose artifact or runtime alignment evidence"; if (deliveryDisabled) { code = "pac-delivery-disabled"; phase = "disabled"; hint = "delivery is disabled by YAML; registry, GitOps and runtime artifacts are intentionally absent"; } else if (!sourceCommit) { ok = false; code = "pac-source-unknown"; phase = "source-unknown"; hint = "latest PaC PipelineRun did not expose a source commit"; } else if (sourceObservationInconsistent) { ok = false; code = "pac-source-observation-inconsistent"; phase = "source-observation-inconsistent"; hint = "structured delivery plan and no-runtime-change terminal markers are incomplete or contradictory"; } else if (sourceObservationMode !== null && !observationSourceMatches) { ok = false; code = "pac-source-observation-mismatch"; phase = "source-observation-mismatch"; hint = "the structured no-runtime-change observation does not belong to the selected PipelineRun source commit"; } else if (noRuntimeChange && retainedOutputConflict) { ok = false; code = "pac-retained-output-conflict"; phase = "source-only-output-conflict"; hint = "a no-runtime-change PipelineRun unexpectedly reported a new artifact or GitOps output"; } else if (noRuntimeChange && retainedRevision === null) { ok = false; code = "pac-retained-gitops-missing"; phase = "retained-gitops-missing"; hint = "the no-runtime-change observation is valid but the retained Argo GitOps revision is missing"; } else if (noRuntimeChange && (argo.sync !== "Synced" || argo.health !== "Healthy")) { ok = false; code = "pac-retained-argo-not-ready"; phase = "retained-argo-not-ready"; hint = "the no-runtime-change observation is valid but retained Argo is not Synced/Healthy"; } else if (noRuntimeChange && gitopsRelation !== "retained") { ok = false; code = "pac-retained-revision-unproven"; phase = "retained-revision-unproven"; hint = "the retained GitOps revision was not linked to the structured no-runtime-change observation"; } else if (noRuntimeChange && !runtimeReady) { ok = false; code = "pac-retained-runtime-not-ready"; phase = "retained-runtime-not-ready"; hint = "the retained runtime ready replicas do not match the desired replica count"; } else if (noRuntimeChange && !retainedDigestReady) { ok = false; code = "pac-retained-runtime-digest-missing"; phase = "retained-runtime-digest-missing"; hint = "the retained runtime is not pinned to a visible sha256 digest"; } else if (noRuntimeChange && !healthReady) { ok = false; code = "pac-retained-health-not-ready"; phase = "retained-health-not-ready"; hint = "the retained runtime health endpoint is not ready"; } else if (noRuntimeChange) { code = "pac-ready-no-runtime-change"; phase = "ready-no-runtime-change"; hint = "the successful source observation requires no artifact, GitOps or runtime change; retained Argo and runtime provenance remain healthy"; } else if (stringOrNull(input.imageRepository) !== null && input.registryPresent !== true) { ok = false; code = "pac-registry-missing"; phase = "source-ready-registry-missing"; hint = "PaC source commit is known but the configured registry tag is missing"; } else if (!registryMatchesArtifact) { ok = false; code = "pac-artifact-registry-mismatch"; phase = "artifact-registry-mismatch"; hint = "PipelineRun artifact digest does not match the configured registry digest"; } else if (!gitopsReady) { ok = false; code = "pac-gitops-missing"; phase = "artifact-ready-gitops-missing"; hint = "PipelineRun completed but its GitOps commit is not visible"; } else if (argo.sync !== "Synced" || argo.health !== "Healthy") { ok = false; code = "pac-argo-not-ready"; phase = "gitops-ready-argo-pending"; hint = "GitOps exists but Argo is not Synced/Healthy"; } else if (!gitopsRevisionAligned) { ok = false; code = `pac-argo-revision-${gitopsRelation}`; phase = `gitops-ready-argo-revision-${gitopsRelation}`; hint = `Argo revision relation is ${gitopsRelation}; only exact or commit-graph-proven descendant is deployable`; } else if (gitopsRelation === "descendant" && !selectedArtifactMatchesRuntime) { ok = false; code = "pac-descendant-artifact-runtime-mismatch"; phase = "argo-descendant-runtime-mismatch"; hint = "a GitOps descendant is ready only when the selected PipelineRun artifact digest exactly matches the runtime digest"; } else if (!runtimeMatches) { ok = false; code = "pac-runtime-not-aligned"; phase = "argo-ready-runtime-mismatch"; hint = "runtime image digest does not match the artifact digest produced by the selected PipelineRun"; } else if (!runtimeReady) { ok = false; code = "pac-runtime-not-ready"; phase = "runtime-replicas-not-ready"; hint = "runtime ready replicas do not match the desired replica count"; } else if (!healthReady) { ok = false; code = "pac-health-not-ready"; phase = "runtime-ready-health-pending"; hint = "runtime image is aligned but the configured health endpoint is not ready"; } else if (artifactDigest || selectedArtifactDigests.length > 0 || stringOrNull(input.imageRepository) !== null) { code = deliverySkipped ? "pac-ready-runtime-unchanged" : gitopsRelation === "descendant" ? "pac-ready-gitops-descendant" : "pac-ready-gitops-exact"; phase = "ready"; hint = deliverySkipped ? "YAML-declared runtime inputs are unchanged; the existing image, GitOps manifest, runtime and health remain aligned" : gitopsRelation === "descendant" ? "Argo is on a commit-graph-proven GitOps descendant and the selected artifact, runtime, Argo and health are aligned" : "Argo is on the exact selected GitOps commit and the artifact, runtime, Argo and health are aligned"; } return { ok, code, phase, hint, sourceCommit, runtimeSourceCommit: stringOrNull(input.runtimeSourceCommit), imageRepository: stringOrNull(input.imageRepository), registryProbeBase: stringOrNull(input.registryProbeBase), imageTag: stringOrNull(input.imageTag), registry: { present: input.registryPresent === true, digest: registryDigest, url: stringOrNull(input.registryUrl), }, selectedArtifactDigests, gitops: { branch: stringOrNull(input.gitopsBranch), manifestPath: stringOrNull(input.gitopsManifestPath), commit: noRuntimeChange ? retainedRevision : stringOrNull(artifact.gitopsCommit) || retainedRevision, revisionRelation, }, argo: { sync: stringOrNull(argo.sync), health: stringOrNull(argo.health), revision: retainedRevision, repoURL: stringOrNull(argo.repoURL), targetRevision: stringOrNull(argo.targetRevision), revisionRelation, }, runtime: { image: runtimeImage, digest: runtimeDigest, readyReplicas: runtime.readyReplicas ?? null, replicas: runtime.replicas ?? null, }, health: { url: healthUrl, status: healthStatus, ready: healthReady }, pipelineRun: stringOrNull(input.pipelineRun), deliveryDisabled, deliverySkipped, deliveryMode: noRuntimeChange ? "no-runtime-change" : sourceObservationMode || "delivery", sourceObservation: Object.keys(sourceObservation).length > 0 ? sourceObservation : null, provenance: noRuntimeChange ? { relation: "retained", sourceCommit, gitopsRevision: retainedRevision, runtimeImage, runtimeDigest, newArtifact: false, newGitopsRevision: false, runtimeChanged: false, valuesPrinted: false, } : { relation: gitopsRelation, sourceCommit, gitopsRevision: retainedRevision, runtimeImage, runtimeDigest, valuesPrinted: false, }, valuesPrinted: false, }; } function fixtureInput(overrides = {}) { const digest = `sha256:${"a".repeat(64)}`; const revision = "b".repeat(40); return { sourceCommit: "c".repeat(40), artifact: {}, argo: { sync: "Synced", health: "Healthy", revision, revisionRelation: { relation: "retained", observedRevision: revision }, }, runtime: { image: `registry/service@${digest}`, digest, replicas: 1, readyReplicas: 1 }, registryPresent: false, healthUrl: null, healthStatus: null, ...overrides, }; } function noRuntimeChangeObservation(sourceCommit = "c".repeat(40)) { return extractPacSourceObservation([ { event: "g14-ci-plan", sourceCommitId: sourceCommit, 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" }, ]); } function deliveryObservation(sourceCommit = "c".repeat(40)) { return extractPacSourceObservation([{ event: "g14-ci-plan", sourceCommitId: sourceCommit, affectedServices: ["service"], rolloutServices: ["service"], buildServices: ["service"], reusedServices: [], }]); } function runPacStatusFixtureChecks() { const digestA = `sha256:${"a".repeat(64)}`; const digestD = `sha256:${"d".repeat(64)}`; const revision = "b".repeat(40); const retained = noRuntimeChangeObservation(); const delivery = deliveryObservation(); const exactArgo = { sync: "Synced", health: "Healthy", revision, revisionRelation: { relation: "exact", expectedRevision: revision, observedRevision: revision } }; const cases = [ { id: "retained-ready", expectedOk: true, expectedCode: "pac-ready-no-runtime-change", input: fixtureInput({ artifact: { imageStatus: "retained", sourceObservation: retained } }), }, { id: "retained-gitops-missing", expectedOk: false, expectedCode: "pac-retained-gitops-missing", input: fixtureInput({ artifact: { imageStatus: "retained", sourceObservation: retained }, argo: { sync: "Synced", health: "Healthy", revision: null, revisionRelation: { relation: "unknown" } } }), }, { id: "delivery-ready-exact", expectedOk: true, expectedCode: "pac-ready-gitops-exact", input: fixtureInput({ artifact: { imageStatus: "built", digest: digestA, digests: [digestA], gitopsCommit: revision, sourceObservation: delivery }, argo: exactArgo, runtime: { image: `registry/service@${digestA}`, digest: digestA, replicas: 1, readyReplicas: 1 } }), }, { id: "delivery-gitops-missing", expectedOk: false, expectedCode: "pac-gitops-missing", input: fixtureInput({ artifact: { imageStatus: "built", digest: digestA, sourceObservation: delivery }, argo: { sync: "Synced", health: "Healthy", revision: null, revisionRelation: { relation: "unknown" } } }), }, { id: "delivery-runtime-mismatch", expectedOk: false, expectedCode: "pac-runtime-not-aligned", input: fixtureInput({ artifact: { imageStatus: "built", digest: digestA, digests: [digestA], gitopsCommit: revision, sourceObservation: delivery }, argo: exactArgo, runtime: { image: `registry/service@${digestD}`, digest: digestD, replicas: 1, readyReplicas: 1 } }), }, { id: "incomplete-no-runtime-change-markers", expectedOk: false, expectedCode: "pac-source-observation-inconsistent", input: fixtureInput({ artifact: { sourceObservation: extractPacSourceObservation([{ event: "g14-ci-plan", sourceCommitId: "c".repeat(40), affectedServices: [], rolloutServices: [], buildServices: [], reusedServices: [] }]) } }), }, { id: "retained-source-mismatch", expectedOk: false, expectedCode: "pac-source-observation-mismatch", input: fixtureInput({ sourceCommit: "e".repeat(40), artifact: { imageStatus: "retained", sourceObservation: retained } }), }, { id: "delivery-one-sided-skip-conflict", expectedOk: false, expectedCode: "pac-source-observation-inconsistent", input: fixtureInput({ artifact: { sourceObservation: extractPacSourceObservation([ { event: "g14-ci-plan", sourceCommitId: "c".repeat(40), affectedServices: ["service"], rolloutServices: ["service"], buildServices: ["service"], reusedServices: [] }, { event: "gitops-promote", status: "skipped", reason: "no-build-no-rollout-plan" }, ]) } }), }, ]; const checks = cases.map((item) => { const result = evaluatePacStatus(item.input); return { id: item.id, ok: result.ok === item.expectedOk && result.code === item.expectedCode, expectedOk: item.expectedOk, actualOk: result.ok, expectedCode: item.expectedCode, actualCode: result.code, }; }); return { ok: checks.every((item) => item.ok), checks, valuesPrinted: false }; } module.exports = { evaluatePacStatus, extractPacSourceObservation, runPacStatusFixtureChecks, };