Skip to content

fix(start-proxy): explicitly fail when proxy retries are exhausted#3531

Open
iaadillatif wants to merge 1 commit intogithub:mainfrom
iaadillatif:fix/start-proxy-retry-exhaustion
Open

fix(start-proxy): explicitly fail when proxy retries are exhausted#3531
iaadillatif wants to merge 1 commit intogithub:mainfrom
iaadillatif:fix/start-proxy-retry-exhaustion

Conversation

@iaadillatif
Copy link

@iaadillatif iaadillatif commented Mar 1, 2026

This PR hardens proxy startup reliability by converting a silent false-success scenario into an explicit failure.

Fixes #3530 issue

Previously, the startup loop could exhaust retry attempts without throwing a terminal error. In such cases, outputs could still be set and execution would continue even though the proxy process was not running.

Before:
Proxy started successfully
[process exited immediately]

After:
Failed to start proxy after 5 attempts (last exit code: 1)

This change ensures that proxy initialization fails fast if stabilization does not occur.


Root Cause

The previous control flow:

  • Retried startup attempts
  • Only threw on immediate spawn error
  • Did not explicitly fail after retry exhaustion
  • Could report success if no process remained alive

This allowed workflows to proceed with a non-functional proxy.


Changes

1. Extracted startup logic

Created src/start-proxy/launcher.ts:

  • Encapsulates startup behavior.
  • Allows dependency injection for testing.
  • Improves separation of concerns.

2. Explicit retry exhaustion handling

  • Tracks lastExitCode.
  • Verifies process remains alive after stabilization delay.
  • Throws Error("Failed to start proxy after 5 attempts (last exit code: X)") when no stable process remains.

3. Tests

Added launcher.test.ts covering:

  • Retry exhaustion with exit code diagnostics.
  • Spawn error propagation.
  • Successful stabilization and output configuration.

Backward Compatibility

  • No change to output names
  • No change to telemetry format
  • No change to wrapper success/failure reporting
  • No new inputs introduced

Behavioral impact is limited to converting silent false-positive startup into explicit failure.


Testing

Executed:

  • npm run lint
  • npm run build
  • npm run test

Added tests in:
src/start-proxy/launcher.test.ts

All new launcher tests pass on Node 24+.

Covering:

  • Exhausted retries
  • Spawn error propagation
  • Stable process success path

Why This Matters

This improves workflow reliability by:

  • Ensuring failures surface at the correct lifecycle stage
  • Reducing downstream noise
  • Providing clearer diagnostics

Fail-fast behavior improves user debugging experience and system robustness.

Copilot AI review requested due to automatic review settings March 1, 2026 19:00
@iaadillatif iaadillatif requested a review from a team as a code owner March 1, 2026 19:00
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens start-proxy startup so that exhausting retries results in an explicit failure (instead of potentially continuing after the proxy has already exited), by extracting proxy launch logic into a dedicated launcher module and adding targeted tests.

Changes:

  • Extracted proxy startup/retry logic into src/start-proxy/launcher.ts and updated the action to call it.
  • Added explicit failure when retries are exhausted, including “last exit code” diagnostics.
  • Added unit tests for success, spawn error propagation, and retry exhaustion behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/start-proxy/launcher.ts New launcher implementing retries, stabilization delay checks, and explicit failure on exhaustion.
src/start-proxy/launcher.test.ts New tests covering retry exhaustion, spawn error propagation, and success path.
src/start-proxy-action.ts Uses the extracted launcher instead of inline startup logic.
lib/start-proxy-action.js Generated build output reflecting the TypeScript changes (not reviewed).

Comment on lines +55 to +59
test("startProxy throws explicit error when retries are exhausted", async (t) => {
const fakeSpawn = sinon.stub().callsFake(() => {
const process = new FakeChildProcess();
// Emit exit on next event loop iteration, ensuring it fires during the delay
setImmediate(() => {
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test will wait on the real util.delay(1000) inside startProxy (and retry scenarios will hit it repeatedly), which will slow down the test suite and can make timing-dependent tests flakier. Consider stubbing util.delay (or injecting a delay function into startProxy) so the tests run quickly and deterministically.

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +49
subprocess.unref();
if (subprocess.pid) {
core.saveState("proxy-process-pid", `${subprocess.pid}`);
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

core.saveState("proxy-process-pid", ...) is called immediately after spawn(), before the stabilization delay. If the child exits during the delay (or on a later retry), the post-action step (start-proxy-action-post.ts) will still read this PID and call process.kill(pid), which can end up targeting an unrelated process if the PID is reused. Consider only saving the PID after the proxy has remained alive past the startup delay (i.e., right before returning success), or otherwise persisting a PID only for the final, stabilized process.

Copilot uses AI. Check for mistakes.
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.

[BUG]: Proxy startup may report success when retries are exhausted and process does not stabilize

2 participants