Skip to content

fix(cli): scope recover.test.ts module mocks so they don't leak to step-runner.test.ts#32336

Merged
dvargasfuertes merged 1 commit into
mainfrom
apollo/fix-cli-exec-secret-leak-test
May 27, 2026
Merged

fix(cli): scope recover.test.ts module mocks so they don't leak to step-runner.test.ts#32336
dvargasfuertes merged 1 commit into
mainfrom
apollo/fix-cli-exec-secret-leak-test

Conversation

@vellum-apollo-bot
Copy link
Copy Markdown
Contributor

Prompt / plan

Fix the only CI failure on main after #32071 merged: (fail) exec — secret leak regression > rejects with an Error whose message contains neither the args nor any -e KEY=VALUE pair.

Root cause

recover.test.ts calls mock.module("../lib/step-runner.js", () => ({ exec: execMock })) at the top of the file, outside any lifecycle hook. Bun 1.3.11's mock.module registration persists across test files in the same bun test invocation (open Bun issue: oven-sh/bun#12823). When the CI test runner reaches step-runner.test.ts, the exec symbol it imports is still pointing at execMock (an async () => {} no-op), not the real spawn-based implementation. The no-op resolves with undefined, so the await exec(...) in the test never rejects, the throw new Error("exec should have rejected") fires, and the assertion expect(message).toContain("sh exited with code 125") fails with Received: "exec should have rejected".

Locally the test passed because file iteration order on my machine put step-runner.test.ts first, before the mock registered. On GHA Ubuntu runners the order was reversed (deterministically — confirmed across 2 CI runs of the same commit).

mock.restore() does not restore module mocks (Bun docs), so the fix is to invert the lifecycle:

  • Capture the real exports of ../lib/local.js and ../lib/step-runner.js at module load time
  • Register the mocks in beforeAll
  • Re-register mock.module with the captured real exports in afterAll

This keeps recover.test.ts's behavior unchanged (all 8 of its tests still pass), and restores the un-mocked exec for any test file that runs after it.

Test plan

  • bun test src/lib/__tests__/step-runner.test.ts src/__tests__/recover.test.ts — both orderings: all 10 step-runner tests pass
  • bun test src/__tests__/recover.test.ts src/lib/__tests__/step-runner.test.ts — reverse order: all pass
  • Full bun run test from cli/: 486/487 pass. The one remaining fail (recover homedir() ... already exists) is a pre-existing local-only collision on my sandbox (/data/.vellum exists from previous work) — also fails on origin/main with the same env, and doesn't reproduce on clean CI runners
  • bun run lint, bun run lint:unused, bun run typecheck, bun build --compile: all green (1 pre-existing eslint-disable warning in roadmap.ts, unchanged from main)

AGENTS.md compliance

@dvargasfuertes dvargasfuertes merged commit 09e6827 into main May 27, 2026
3 checks passed
@dvargasfuertes dvargasfuertes deleted the apollo/fix-cli-exec-secret-leak-test branch May 27, 2026 21:52
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