From 7294800dec4ce72a3350a96630cc73e05dbf3375 Mon Sep 17 00:00:00 2001 From: Lyon <88232613+pikasTech@users.noreply.github.com> Date: Mon, 22 Jun 2026 15:10:54 +0800 Subject: [PATCH] fix: render node git mirror summary (#660) Co-authored-by: Codex --- scripts/src/hwlab-node-impl.ts | 90 +++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/scripts/src/hwlab-node-impl.ts b/scripts/src/hwlab-node-impl.ts index c18d7bcb..591f9125 100644 --- a/scripts/src/hwlab-node-impl.ts +++ b/scripts/src/hwlab-node-impl.ts @@ -382,10 +382,14 @@ async function runNodeDelegatedDomain(config: Config, domain: DelegatedNodeDomai return nodeRuntimeUnsupportedAction(scoped); } if (domain === "git-mirror" && scoped.node !== defaultSpec.nodeId) { - if (scoped.action === "status") return nodeRuntimeGitMirrorStatus(scoped); + if (scoped.action === "status") { + const result = nodeRuntimeGitMirrorStatus(scoped); + return nodeScopedFullOutput(scoped) ? result : withNodeRuntimeGitMirrorRendered(result, scoped); + } if (scoped.action === "sync" || scoped.action === "flush") { if (scoped.confirm && !scoped.dryRun && !scoped.wait) return startNodeDelegatedJob(scoped); - return nodeRuntimeGitMirrorRun(scoped); + const result = nodeRuntimeGitMirrorRun(scoped); + return nodeScopedFullOutput(scoped) ? result : withNodeRuntimeGitMirrorRendered(result, scoped); } return nodeRuntimeUnsupportedAction(scoped); } @@ -3489,6 +3493,88 @@ function compactNodeRuntimeGitMirrorRun(result: Record): Record }; } +function withNodeRuntimeGitMirrorRendered(result: Record, scoped: ReturnType): RenderedCliResult { + const status = record(result.status); + const summary = scoped.action === "status" ? record(result.summary) : record(status.summary); + const retry = record(result.retry); + const retryAttempts = Array.isArray(retry.attempts) ? retry.attempts.map(record).filter((item): item is Record => item !== null) : []; + const retryText = typeof retry.maxAttempts === "number" + ? `${retryAttempts.length}/${retry.maxAttempts}${retry.exhausted === true ? " exhausted" : ""}` + : "-"; + const transport = record(result.githubTransport); + const commandResult = record(result.result); + const retryableFailure = record(result.retryableFailure); + const next = record(result.next); + const resultStatus = result.ok === true ? "ok" : result.ok === false ? "failed" : "-"; + const lines = [ + `hwlab nodes git-mirror ${scoped.action}`, + "", + webObserveTable( + ["NODE", "LANE", "ACTION", "STATUS", "MODE", "JOB", "RETRY"], + [[ + scoped.node, + scoped.lane, + scoped.action, + resultStatus, + webObserveText(result.mode), + webObserveShort(webObserveText(result.jobName), 36), + retryText, + ]], + ), + "", + Object.keys(summary).length === 0 + ? "REFS\n-" + : webObserveTable( + ["LOCAL_SOURCE", "GITHUB_SOURCE", "LOCAL_GITOPS", "GITHUB_GITOPS", "PENDING", "IN_SYNC"], + [[ + shortValue(summary.localSource), + shortValue(summary.githubSource), + shortValue(summary.localGitops), + shortValue(summary.githubGitops), + webObserveText(summary.pendingFlush), + webObserveText(summary.githubInSync), + ]], + ), + "", + Object.keys(transport).length === 0 + ? "TRANSPORT\n-" + : webObserveTable( + ["MODE", "READY", "REQUIRED"], + [[webObserveText(transport.mode), webObserveText(transport.ready), webObserveText(transport.required)]], + ), + "", + Object.keys(commandResult).length === 0 + ? "RESULT\n-" + : webObserveTable( + ["EXIT", "TIMED_OUT", "STDOUT_BYTES", "STDERR_BYTES"], + [[ + webObserveText(commandResult.exitCode), + webObserveText(commandResult.timedOut), + webObserveText(commandResult.stdoutBytes), + webObserveText(commandResult.stderrBytes), + ]], + ), + "", + Object.keys(retryableFailure).length === 0 + ? "RETRYABLE\n-" + : webObserveTable( + ["RETRYABLE", "EXHAUSTED", "REASON"], + [[ + webObserveText(retryableFailure.retryable), + webObserveText(retryableFailure.exhausted), + webObserveShort(webObserveText(retryableFailure.reason ?? retryableFailure.degradedReason), 100), + ]], + ), + "", + "NEXT", + ` ${next.status ?? next.sync ?? next.flush ?? next.retry ?? next.run ?? `bun scripts/cli.ts hwlab nodes git-mirror status --node ${scoped.node} --lane ${scoped.lane}`}`, + "", + "Disclosure:", + " default view is a bounded git-mirror summary; use --full or --raw for the complete JSON payload.", + ]; + return { ...result, renderedText: lines.join("\n"), contentType: "text/plain" }; +} + function compactNodeRuntimeGitMirrorStatus(status: Record): Record { const summary = record(status.summary); return {