From 7b1ea7080e94c2885f2c44a11929c04c20290856 Mon Sep 17 00:00:00 2001 From: luvs01 Date: Thu, 13 Aug 2026 09:34:09 +0900 Subject: [PATCH] fix(cli): preserve service command exit failures --- src/cli/dispatch.ts | 6 +++--- src/cli/index.ts | 1 + tests/cli-dispatch.test.ts | 21 +++++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/cli/dispatch.ts b/src/cli/dispatch.ts index d84d6b7151..bcca075e2a 100644 --- a/src/cli/dispatch.ts +++ b/src/cli/dispatch.ts @@ -21,7 +21,6 @@ import { restoreNativeCodexAsync } from "../codex/inject"; import { stripGrokConfig } from "../grok/inject"; import { afterCatalogWriteHandleAppServers } from "../codex/app-server-processes"; import { normalizeUpdateChannel, runGuiUpdateWorker } from "../update/job"; -import { serviceCommand } from "../service"; export interface CliDispatchDeps { args: string[]; @@ -45,6 +44,7 @@ export interface CliDispatchDeps { handleStatus: () => Promise; handleRecoverHistory: () => Promise; handleReady: (args: ReadyArgs) => Promise; + serviceCommand: (...args: string[]) => Promise; } type CommandRunner = (deps: CliDispatchDeps) => Promise; @@ -261,8 +261,8 @@ const commandRunners: Record = { return 0; }, service: async deps => { - await serviceCommand(...deps.args.slice(1)); - return 0; + await deps.serviceCommand(...deps.args.slice(1)); + return Number(process.exitCode ?? 0); }, tray: async deps => { const { windowsTrayCommand } = await import("../tray/windows"); diff --git a/src/cli/index.ts b/src/cli/index.ts index e67f7a8b8c..940201ab21 100755 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -941,4 +941,5 @@ process.exit(await dispatchCommand(head, { handleStatus, handleRecoverHistory, handleReady, + serviceCommand, })); diff --git a/tests/cli-dispatch.test.ts b/tests/cli-dispatch.test.ts index 0fa501494d..307dbf567c 100644 --- a/tests/cli-dispatch.test.ts +++ b/tests/cli-dispatch.test.ts @@ -76,4 +76,25 @@ describe("dispatchCommand exit codes", () => { expect(await dispatchCommand(head, fakeDeps), `${name} must be unknown`).toBe(1); } }); + + test("preserves a failure exit code set by the service command", async () => { + const previousExitCode = process.exitCode; + try { + process.exitCode = undefined; + const deps = { + ...fakeDeps, + args: ["service", "start"], + serviceCommand: async () => { + process.exitCode = 1; + }, + }; + + expect(await dispatchCommand( + { kind: "command", command: "service", args: deps.args }, + deps, + )).toBe(1); + } finally { + process.exitCode = previousExitCode; + } + }); });