Skip to content

fix: propagate non-zero exit codes from deploy client#989

Open
LongOddCode wants to merge 4 commits intomainfrom
developer/LongOddCode/fix-swa-deploy-silent-failure
Open

fix: propagate non-zero exit codes from deploy client#989
LongOddCode wants to merge 4 commits intomainfrom
developer/LongOddCode/fix-swa-deploy-silent-failure

Conversation

@LongOddCode
Copy link
Copy Markdown
Contributor

@LongOddCode LongOddCode commented Apr 9, 2026

Summary

Fixes #665

The deploy() function spawned the deploy client binary (StaticSitesClient) but never awaited the child process. The close event handler ran in a fire-and-forget callback, so a non-zero exit code was silently ignored and the function always resolved — making CI/CD pipelines believe deployment succeeded even when it failed.

Changes

src/cli/commands/deploy/deploy.ts

  • Wrap the spawn() call and its event handlers in new Promise and await it
  • Reject the promise on non-zero exit codes with a descriptive error message
  • Reject on signal kills (e.g., SIGTERM)
  • Reject on spawn errors (e.g., ENOENT when binary not found)
  • Add a settled guard to prevent double-resolution edge cases
  • Re-throw caught errors in the catch block (previously swallowed silently)
  • Moved cleanUp() out of the close handler into the existing finally block

src/cli/commands/deploy/deploy-exit-code.spec.ts (NEW)

  • 6 focused unit tests for exit code propagation:
    • Rejects on non-zero exit code
    • Resolves on exit code 0
    • Rejects when killed by signal
    • Rejects on spawn error events
    • Verifies cleanUp() is called after failure
    • Verifies logGitHubIssueMessageAndExit() is called on failure

The deploy command silently ignored failures from the StaticSitesClient
binary. When the binary crashed (e.g., missing native dependencies on
slim Docker images), the CLI reported success and exited with code 0.

This fix:
- Adds stderr handler to capture binary error output
- Adds else branch for non-zero exit codes with diagnostic message
- Calls process.exit(1) on failure so CI/CD detects it

Fixes #536, #594
Refs: ICM 21000000909499
- stderr is captured and passed to logger.error
- Non-zero exit code triggers spinner.fail and error message
- process.exit(1) is called on binary failure
- Success path (exit code 0) remains unchanged
The ReturnType<typeof vi.spyOn> didn't match the 'never' return type of
process.exit, causing tsc to fail in CI format check.
The deploy e2e CI uses --dry-run with a dummy token, which causes
StaticSitesClient to fail with BadRequest. In dry-run mode, binary
failures should be logged but not cause process.exit(1).

Added test: 'should not call process.exit(1) in dry-run mode'
@LongOddCode LongOddCode changed the title fix: handle StaticSitesClient stderr and non-zero exit codes fix: propagate non-zero exit codes from deploy client Apr 10, 2026
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.

Getting zero exit code on deploy failure

1 participant