diff --git a/scripts/src/platform-infra-pipelines-as-code.ts b/scripts/src/platform-infra-pipelines-as-code.ts index 9b9ecc43..e80193c2 100644 --- a/scripts/src/platform-infra-pipelines-as-code.ts +++ b/scripts/src/platform-infra-pipelines-as-code.ts @@ -561,11 +561,11 @@ async function closeout(config: UniDeskConfig, options: CloseoutOptions): Promis const waitMs = Math.max(1, pac.release.waitTimeoutSeconds) * 1000; let ciAttempts = 0; let runtimeAttempts = 0; - let current = await status(config, options); + let current = await observeCloseoutStatus(config, options, target, consumer, "ci", 1, startedAt); ciAttempts += 1; while (options.wait && !closeoutCiReady(current, options.sourceCommit) && Date.now() - startedAt < waitMs) { await sleep(3000); - current = await status(config, options); + current = await observeCloseoutStatus(config, options, target, consumer, "ci", ciAttempts + 1, startedAt); ciAttempts += 1; } let summary = record(current.summary); @@ -574,15 +574,25 @@ async function closeout(config: UniDeskConfig, options: CloseoutOptions): Promis let observedSourceCommit = observedCloseoutSourceCommit(latest, diagnostics); let sourceMatched = options.sourceCommit === null || observedSourceCommit === options.sourceCommit; const ciReady = closeoutCiReady(current, options.sourceCommit); + printCloseoutProgress(target, consumer, "gitops-mirror-flush", "started", startedAt, { + required: pac.closeout.gitOpsMirrorFlush.enabled && consumer.closeoutGitOpsMirrorFlush, + ciReady, + sourceCommit: observedSourceCommit, + }); let gitOpsMirrorFlush = await runCloseoutGitOpsMirrorFlush(config, pac, consumer, summary, latest, ciReady, observedSourceCommit); + printCloseoutProgress(target, consumer, "gitops-mirror-flush", record(gitOpsMirrorFlush).ok === false ? "failed" : "completed", startedAt, { + mode: record(gitOpsMirrorFlush).mode, + executed: record(gitOpsMirrorFlush).executed === true, + required: record(gitOpsMirrorFlush).required === true, + }); const gitOpsMirrorFlushReady = record(gitOpsMirrorFlush).ok !== false; const runtimeStartedAt = Date.now(); if (ciReady && gitOpsMirrorFlushReady) { - current = await status(config, options); + current = await observeCloseoutStatus(config, options, target, consumer, "runtime", 1, startedAt); runtimeAttempts += 1; while (options.wait && !closeoutReady(current, options.sourceCommit) && Date.now() - runtimeStartedAt < waitMs) { await sleep(3000); - current = await status(config, options); + current = await observeCloseoutStatus(config, options, target, consumer, "runtime", runtimeAttempts + 1, startedAt); runtimeAttempts += 1; } } @@ -598,6 +608,13 @@ async function closeout(config: UniDeskConfig, options: CloseoutOptions): Promis valuesPrinted: false, }; const ready = baseReady && gitOpsMirrorFlushReady; + printCloseoutProgress(target, consumer, "closeout", ready ? "completed" : "blocked", startedAt, { + ready, + sourceMatched, + diagnosticCode: diagnostics.code, + ciAttempts, + runtimeAttempts, + }); return { ok: ready, action: "platform-infra-pipelines-as-code-closeout", @@ -628,6 +645,35 @@ async function closeout(config: UniDeskConfig, options: CloseoutOptions): Promis }; } +async function observeCloseoutStatus(config: UniDeskConfig, options: CloseoutOptions, target: PacTarget, consumer: PacConsumer, phase: "ci" | "runtime", attempt: number, startedAt: number): Promise> { + printCloseoutProgress(target, consumer, `${phase}-status`, "started", startedAt, { attempt }); + const current = await status(config, options); + const summary = record(current.summary); + const latest = record(summary.latestPipelineRun); + const diagnostics = record(summary.diagnostics); + printCloseoutProgress(target, consumer, `${phase}-status`, "observed", startedAt, { + attempt, + ready: current.ok === true, + pipelineRun: latest.name, + sourceCommit: observedCloseoutSourceCommit(latest, diagnostics), + diagnosticCode: diagnostics.code, + }); + return current; +} + +function printCloseoutProgress(target: PacTarget, consumer: PacConsumer, stage: string, status: string, startedAt: number, detail: Record): void { + process.stderr.write(`${JSON.stringify({ + event: "platform-infra.pipelines-as-code.closeout.progress", + stage, + status, + target: target.id, + consumer: consumer.id, + elapsedMs: Date.now() - startedAt, + ...detail, + valuesPrinted: false, + })}\n`); +} + async function history(config: UniDeskConfig, options: HistoryOptions): Promise> { const pac = readPacConfig(); const target = resolveTarget(pac, options.targetId); @@ -1923,7 +1969,7 @@ async function runCloseoutGitOpsMirrorFlush(config: UniDeskConfig, pac: PacConfi String(cfg.waitTimeoutSeconds), ]); const progressLines: string[] = []; - const flush = captureStderrLines(progressLines, () => nodeRuntimeEnsureGitMirrorFlushed(scoped, "post", observedSourceCommit, pipelineRun, null, { + const flush = await captureStderrLines(progressLines, () => nodeRuntimeEnsureGitMirrorFlushed(scoped, "post", observedSourceCommit, pipelineRun, null, { deadlineMs, maxAttempts: cfg.maxAttempts, })); @@ -1949,17 +1995,19 @@ async function runCloseoutGitOpsMirrorFlush(config: UniDeskConfig, pac: PacConfi }; } -function captureStderrLines(lines: string[], callback: () => T): T { +async function captureStderrLines(lines: string[], callback: () => T | Promise): Promise { const stderr = process.stderr as typeof process.stderr & { write: (...args: unknown[]) => boolean }; const originalWrite = stderr.write.bind(process.stderr); stderr.write = ((chunk: unknown, ...args: unknown[]): boolean => { - lines.push(Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk)); + const text = Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk); + lines.push(text); + originalWrite(text); const callbackArg = args.find((arg) => typeof arg === "function") as (() => void) | undefined; callbackArg?.(); return true; }) as typeof stderr.write; try { - return callback(); + return await callback(); } finally { stderr.write = originalWrite as typeof stderr.write; }