From 4102e2f1b8daaaef9c1dc38fd09d5c6f19ba28af Mon Sep 17 00:00:00 2001 From: Benjamin Jesuiter Date: Sun, 11 Jan 2026 01:14:59 +0100 Subject: [PATCH] refactor(update): simplify progress with proper exit codes --- src/cli/update-cli.ts | 11 +++----- src/infra/update-runner.ts | 52 ++++++++++---------------------------- 2 files changed, 16 insertions(+), 47 deletions(-) diff --git a/src/cli/update-cli.ts b/src/cli/update-cli.ts index 8326c7a46..febda8a07 100644 --- a/src/cli/update-cli.ts +++ b/src/cli/update-cli.ts @@ -19,8 +19,8 @@ export type UpdateCommandOptions = { }; const STEP_LABELS: Record = { - "git status": "Checking for uncommitted changes", - "git upstream": "Checking upstream branch", + "clean check": "Working directory is clean", + "upstream check": "Upstream branch exists", "git fetch": "Fetching latest changes", "git rebase": "Rebasing onto upstream", "deps install": "Installing dependencies", @@ -60,13 +60,8 @@ function createUpdateProgress(enabled: boolean): ProgressController { const label = getStepLabel(step); const duration = theme.muted(`(${formatDuration(step.durationMs)})`); - const icon = - step.status === "success" - ? theme.success("\u2713") - : step.status === "skipped" - ? theme.warn("\u25CB") - : theme.error("\u2717"); + step.exitCode === 0 ? theme.success("\u2713") : theme.error("\u2717"); currentSpinner.stop(`${icon} ${label} ${duration}`); currentSpinner = null; diff --git a/src/infra/update-runner.ts b/src/infra/update-runner.ts index 7c6b9881a..bc1138fda 100644 --- a/src/infra/update-runner.ts +++ b/src/infra/update-runner.ts @@ -37,12 +37,9 @@ export type UpdateStepInfo = { total: number; }; -export type StepStatus = "success" | "error" | "skipped"; - export type UpdateStepCompletion = UpdateStepInfo & { durationMs: number; exitCode: number | null; - status: StepStatus; }; export type UpdateStepProgress = { @@ -175,11 +172,7 @@ type RunStepOptions = { totalSteps: number; }; -type StepResultWithReport = UpdateStepResult & { - reportComplete: (status: StepStatus) => void; -}; - -async function runStep(opts: RunStepOptions): Promise { +async function runStep(opts: RunStepOptions): Promise { const { runCommand, name, @@ -206,14 +199,11 @@ async function runStep(opts: RunStepOptions): Promise { const result = await runCommand(argv, { cwd, timeoutMs, env }); const durationMs = Date.now() - started; - const reportComplete = (status: StepStatus) => { - progress?.onStepComplete?.({ - ...stepInfo, - durationMs, - exitCode: result.code, - status, - }); - }; + progress?.onStepComplete?.({ + ...stepInfo, + durationMs, + exitCode: result.code, + }); return { name, @@ -223,7 +213,6 @@ async function runStep(opts: RunStepOptions): Promise { exitCode: result.code, stdoutTail: trimLogTail(result.stdout, MAX_LOG_CHARS), stderrTail: trimLogTail(result.stderr, MAX_LOG_CHARS), - reportComplete, }; } @@ -312,17 +301,15 @@ export async function runGatewayUpdate( const beforeSha = beforeShaResult.stdout.trim() || null; const beforeVersion = await readPackageVersion(gitRoot); - const statusStep = await runStep( + const cleanCheck = await runStep( step( - "git status", - ["git", "-C", gitRoot, "status", "--porcelain"], + "clean check", + ["sh", "-c", `test -z "$(git -C '${gitRoot}' status --porcelain)"`], gitRoot, ), ); - const isDirty = (statusStep.stdoutTail ?? "").trim().length > 0; - statusStep.reportComplete(isDirty ? "skipped" : "success"); - steps.push(statusStep); - if (isDirty) { + steps.push(cleanCheck); + if (cleanCheck.exitCode !== 0) { return { status: "skipped", mode: "git", @@ -336,7 +323,7 @@ export async function runGatewayUpdate( const upstreamStep = await runStep( step( - "git upstream", + "upstream check", [ "git", "-C", @@ -349,10 +336,8 @@ export async function runGatewayUpdate( gitRoot, ), ); - const hasUpstream = upstreamStep.exitCode === 0; - upstreamStep.reportComplete(hasUpstream ? "success" : "skipped"); steps.push(upstreamStep); - if (!hasUpstream) { + if (upstreamStep.exitCode !== 0) { return { status: "skipped", mode: "git", @@ -371,7 +356,6 @@ export async function runGatewayUpdate( gitRoot, ), ); - fetchStep.reportComplete(fetchStep.exitCode === 0 ? "success" : "error"); steps.push(fetchStep); const rebaseStep = await runStep( @@ -381,7 +365,6 @@ export async function runGatewayUpdate( gitRoot, ), ); - rebaseStep.reportComplete(rebaseStep.exitCode === 0 ? "success" : "error"); steps.push(rebaseStep); if (rebaseStep.exitCode !== 0) { const abortResult = await runCommand( @@ -413,21 +396,16 @@ export async function runGatewayUpdate( const depsStep = await runStep( step("deps install", managerInstallArgs(manager), gitRoot), ); - depsStep.reportComplete(depsStep.exitCode === 0 ? "success" : "error"); steps.push(depsStep); const buildStep = await runStep( step("build", managerScriptArgs(manager, "build"), gitRoot), ); - buildStep.reportComplete(buildStep.exitCode === 0 ? "success" : "error"); steps.push(buildStep); const uiBuildStep = await runStep( step("ui:build", managerScriptArgs(manager, "ui:build"), gitRoot), ); - uiBuildStep.reportComplete( - uiBuildStep.exitCode === 0 ? "success" : "error", - ); steps.push(uiBuildStep); const doctorStep = await runStep( @@ -438,7 +416,6 @@ export async function runGatewayUpdate( { CLAWDBOT_UPDATE_IN_PROGRESS: "1" }, ), ); - doctorStep.reportComplete(doctorStep.exitCode === 0 ? "success" : "error"); steps.push(doctorStep); const failedStep = steps.find((s) => s.exitCode !== 0); @@ -449,9 +426,6 @@ export async function runGatewayUpdate( gitRoot, ), ); - afterShaStep.reportComplete( - afterShaStep.exitCode === 0 ? "success" : "error", - ); steps.push(afterShaStep); const afterVersion = await readPackageVersion(gitRoot);