fix: gate PaC closeout on PipelineRun success

This commit is contained in:
Codex
2026-07-07 00:30:07 +00:00
parent 46423e046b
commit 69a6c187bd
@@ -679,14 +679,16 @@ function statusSummary(payload: Record<string, unknown>): Record<string, unknown
digest: record(payload.artifact).digest ?? runtime.digest,
gitopsCommit: record(payload.artifact).gitopsCommit ?? argo.revision,
};
const pipelineGate = pipelineRunGate(latest);
return {
ready: payload.crdPresent === true && String(payload.controllerReady ?? "0/0") !== "0/0" && diagnostics.ok !== false,
ready: payload.crdPresent === true && String(payload.controllerReady ?? "0/0") !== "0/0" && pipelineGate.ok && diagnostics.ok !== false,
crdPresent: payload.crdPresent === true,
controllerReady: payload.controllerReady,
repositoryCondition: payload.repositoryCondition,
webhookCount: arrayRecords(payload.webhooks).length,
latestPipelineRun: latest,
taskRuns,
pipelineRunGate: pipelineGate,
artifact,
argo,
runtime,
@@ -1108,6 +1110,19 @@ function closeoutBlocker(value: Record<string, unknown>, expected: string | null
};
}
const summary = record(value.summary);
const latest = record(summary.latestPipelineRun);
const pipelineGate = pipelineRunGate(latest);
if (!pipelineGate.ok) {
const longestTask = longestTaskRun(arrayRecords(summary.taskRuns));
const longestTaskText = longestTask === null
? "longestTask=-"
: `longestTask=${stringValue(longestTask.name)} status=${statusText(longestTask)} duration=${stringValue(longestTask.durationSeconds)}s`;
return {
code: pipelineGate.code,
reason: `${pipelineGate.reason}; pipelineRun=${stringValue(latest.name)} duration=${stringValue(latest.durationSeconds)}s; ${longestTaskText}`,
valuesPrinted: false,
};
}
const diagnostics = record(summary.diagnostics);
return {
code: stringValue(diagnostics.code, "pac-closeout-not-ready"),
@@ -1120,6 +1135,54 @@ function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function pipelineRunGate(latest: Record<string, unknown>): Record<string, unknown> {
const name = stringValue(latest.name);
if (name === "-") {
return {
ok: false,
code: "pipeline-missing",
reason: "no matching PipelineRun is visible yet",
valuesPrinted: false,
};
}
const status = stringValue(latest.status);
const reason = stringValue(latest.reason);
if (status === "True") {
return {
ok: true,
code: "pipeline-succeeded",
reason: reason === "-" ? "PipelineRun completed successfully" : `PipelineRun ${reason}`,
valuesPrinted: false,
};
}
if (status === "False") {
return {
ok: false,
code: "pipeline-failed",
reason: reason === "-" ? "PipelineRun completed with failure" : `PipelineRun failed: ${reason}`,
valuesPrinted: false,
};
}
return {
ok: false,
code: "pipeline-running",
reason: statusText(latest) === "-" ? "PipelineRun is not terminal" : `PipelineRun is ${statusText(latest)}`,
valuesPrinted: false,
};
}
function longestTaskRun(taskRuns: Record<string, unknown>[]): Record<string, unknown> | null {
let selected: Record<string, unknown> | null = null;
let selectedDuration = -1;
for (const taskRun of taskRuns) {
const duration = numericValue(taskRun.durationSeconds);
if (duration === null || duration < selectedDuration) continue;
selected = taskRun;
selectedDuration = duration;
}
return selected;
}
function positiveInteger(obj: Record<string, unknown>, key: string, path: string): number {
const value = y.integerField(obj, key, path);
if (value < 1) throw new Error(`${configLabel}.${path}.${key} must be positive`);
@@ -1172,6 +1235,13 @@ function stringValue(value: unknown, fallback = "-"): string {
return fallback;
}
function numericValue(value: unknown): number | null {
if (typeof value === "number" && Number.isFinite(value)) return value;
if (typeof value !== "string" || value.trim().length === 0) return null;
const parsed = Number(value);
return Number.isFinite(parsed) ? parsed : null;
}
function boolText(value: unknown): string {
return value === true ? "true" : "false";
}