diff --git a/scripts/src/cicd.ts b/scripts/src/cicd.ts index 50f6d022..f65fb5f7 100644 --- a/scripts/src/cicd.ts +++ b/scripts/src/cicd.ts @@ -782,6 +782,7 @@ async function decideAndMaybeTrigger( } else if (targetSha !== null && targetSha === observedSha && live.aligned === true) { phase = "Noop"; decision = "target already matches observed source sha"; + inFlightJob = null; lastSucceededSha = observedSha; } else if (lastTriggeredSha !== null && lastTriggeredSha === observedSha && live.pipelineRunPresent === true) { phase = "ClosingOut"; @@ -2122,7 +2123,8 @@ function buildFollowerTimings( phase?: BranchFollowerPhase, ): FollowerState["timings"] { const nativePayload = asOptionalRecord(live.payload); - const total = totalTimingFromCommand(triggerCommand, phase) ?? totalTimingFromStored(storedTimings, phase, stringOrNull(triggerCommand?.finishedAt), live.observedSha); + const finishOverride = stringOrNull(triggerCommand?.finishedAt) ?? noopStoredTotalFinishOverride(storedTimings, phase, live); + const total = totalTimingFromCommand(triggerCommand, phase) ?? totalTimingFromStored(storedTimings, phase, finishOverride, live.observedSha); const stages = dedupeTimingStages([ ...stageTimingsFromCommand(triggerCommand), ...stageTimingsFromNativePayload(nativePayload), @@ -2141,6 +2143,19 @@ function buildFollowerTimings( }; } +function noopStoredTotalFinishOverride( + storedTimings: Record | null | undefined, + phase: BranchFollowerPhase | undefined, + live: AdapterSummary, +): string | null { + if (phase !== "Noop" || live.aligned !== true || live.observedSha === null) return null; + if (storedTimings === null || storedTimings === undefined) return null; + if (stringOrNull(storedTimings.sourceCommit) !== live.observedSha) return null; + if (stringOrNull(storedTimings.startedAt) === null) return null; + if (stringOrNull(storedTimings.finishedAt) !== null) return null; + return new Date().toISOString(); +} + function storedFollowerTimingsForStatus( follower: FollowerSpec, storedTimings: Record | null,