diff --git a/scripts/src/platform-infra-pipelines-as-code.ts b/scripts/src/platform-infra-pipelines-as-code.ts index 90515491..10eec0c9 100644 --- a/scripts/src/platform-infra-pipelines-as-code.ts +++ b/scripts/src/platform-infra-pipelines-as-code.ts @@ -679,14 +679,16 @@ function statusSummary(payload: Record): Record, 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 { return new Promise((resolve) => setTimeout(resolve, ms)); } +function pipelineRunGate(latest: Record): Record { + 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[]): Record | null { + let selected: Record | 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, 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"; }