Skip to content

fix: stop swallowing failure exit codes#48

Merged
robrechtme merged 1 commit into
mainfrom
fix/exit-code-handling
May 5, 2026
Merged

fix: stop swallowing failure exit codes#48
robrechtme merged 1 commit into
mainfrom
fix/exit-code-handling

Conversation

@robrechtme
Copy link
Copy Markdown
Owner

@robrechtme robrechtme commented May 5, 2026

Summary

  • handleAsyncErrors previously caught errors but never set a non-zero exit code — failed pulls/pushes silently passed in CI. It now always sets process.exitCode = 1 on a caught error.
  • Introduces CliError for the "we've already printed a friendly user-facing message, just exit 1" case. handleAsyncErrors recognizes it and skips the generic error wrapper.
  • Removes every process.exit(0|1) call from command bodies (pull, push, status) and helpers (getGlobalOptions, readFiles). Successful paths just return; failure paths log + throw new CliError(...).
  • Tests no longer need the ExitError / process.exit spy workaround. Added 5 unit tests for handleAsyncErrors covering the regression.

Test plan

  • pnpm build && pnpm test && pnpm lint && pnpm format:check all pass
  • loco-cli status with no diff exits 0
  • loco-cli status with a diff exits 1
  • loco-cli pull / push with a missing/invalid access key exits 1 (and prints the access-key hint)
  • loco-cli pull with n at the prompt exits 0 (user declined ≠ error)
  • loco-cli push against a quota-capped project (Loco returns "Nothing updated") exits 1 with the explanatory message

…mand bodies

`handleAsyncErrors` previously logged caught errors and let the process
exit 0 — so a failed pull/push (401, network error, file-not-found) silently
passed in CI. It now sets `process.exitCode = 1` on every caught error.

Commands no longer call `process.exit` directly. Successful paths just
return; failure paths log the user-facing message and throw a new
`CliError`, which `handleAsyncErrors` translates to exit code 1 without
re-printing. Tests no longer need the `ExitError` / `process.exit` spy
workaround.

- Add `CliError` for "we already printed a friendly message, just exit 1"
- `handleAsyncErrors` always sets `process.exitCode = 1` on a caught error
- Replace every `process.exit(0|1)` in commands and helpers with `return`
  or `throw new CliError(...)`
- Add `handleAsyncErrors` unit tests covering the regression
@vercel
Copy link
Copy Markdown

vercel Bot commented May 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
loco-cli Ready Ready Preview, Comment May 5, 2026 9:04am

@robrechtme robrechtme merged commit 3da9c33 into main May 5, 2026
3 checks passed
@robrechtme robrechtme deleted the fix/exit-code-handling branch May 5, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant