Skip to content

test(hooks): make the pre-push tsx stub path survive .git-less cloud image checkouts - #816

Merged
danshapiro merged 1 commit into
mainfrom
fix/cloud-vitest-tsx-stub-loop
Sep 20, 2026
Merged

danshapiro merged 1 commit into
mainfrom
fix/cloud-vitest-tsx-stub-loop

Conversation

@danshapiro

Copy link
Copy Markdown
Owner

Summary

The Cloud Run vitest lane has been silently hanging since the pre-push hook
routing tests landed (ba83dd4, Sep 19): every cloud test:unit run wedges
one shard forever and fails at the 30-minute job timeout with zero test
failures
. This breaks every agent's green-base gate and full-suite run on
the cloud backend (two scripts/base-gate.sh test attempts at 8dea394 both
went red this way: 539/540 test files green, one file never completing, in
both runs).

Root cause

test/unit/scripts/rust-test-targets.test.ts derives the real tsx binary
for its hook fixture from the git common dir:

  1. The Cloud Run image copies the source tree without .git
    (.dockerignore excludes it), so the module-level
    git rev-parse --git-common-dir probe fails with empty stdout.
  2. The old code fell back to path.join('', ...) — the relative
    node_modules/.bin/tsx.
  3. The fixture stub is #!/bin/sh exec "<path>" "$@"; invoked from the
    fixture repo, a relative path re-execs the stub itself in an infinite
    silent loop
    (no output, no failure).
  4. spawnSync had no timeout, so the vitest worker blocks until the job
    timeout reaps the shard.

Locally this never reproduces (the checkout has .git).

Verified in the exact production image
(freshell-e2e:8dea394d996b, --network=none, worktree file overlaid):

  • git rev-parse from /app/test/unit/scripts: exit 128, empty stdout.
  • The relative-path stub loops (killed only by timeout, exit 124).
  • The original test file wedges vitest so hard it never finishes —
    it survives its own 90-second SIGTERM deadline (the container never
    exits).
  • The fixed file: 29/29 in 3.5s in the same image.

Fix (test-only)

  • owningTsxPath(): fall back to the checkout root containing the test
    file when git metadata is absent, and force an absolute result so the
    stub can never self-exec-loop.
  • spawnSync timeouts (15s/30s/120s) so a wedged child fails the test in
    bounded time instead of eating the 30-minute job.

No production code changes.

Verification

  • New unit tests pin both the git-present behavior and the no-git fallback
    (red → green).
  • Full default-config local unit suite green (489 files), including the
    fixed file's 29 tests.
  • Cloud Run vitest lane on this branch: green (4 shards, image built at
    05a89bb).

Test plan

  • npm run test:vitest -- run test/unit/scripts/rust-test-targets.test.ts --config config/vitest/vitest.config.ts — 29/29.
  • Cloud lane on the branch: FRESHELL_VITEST_BACKEND=cloud npm run test:unit — exit 0.

…image checkouts

The rust-test-targets hook-routing test derives the real tsx binary from
the git common dir. The Cloud Run vitest image ships the source tree
without .git (.dockerignore), so the probe fails there and the old code
fell back to path.join('', ...) — a RELATIVE node_modules/.bin/tsx. The
fixture stub execs that path from the fixture repo, so a relative path
re-execs the stub itself in a silent infinite loop: the shard hangs
until the 30-minute job timeout with zero test failures. This broke every
cloud vitest run since the test landed (both 8dea394 green-base gates
hung 539/540 files green, one shard wedged; reproduced in the exact
image: original file never finishes, even past its own SIGTERM).

- owningTsxPath(): fall back to the checkout root containing the test
  file when git metadata is absent, and force an absolute result so the
  stub can never self-exec-loop.
- add spawnSync timeouts (15s/30s/120s) so a wedged child fails the
  test in bounded time instead of eating the job.

Verified in the exact production image (freshell-e2e:8dea394d996b,
--network=none): fixed file 29/29 in 3.5s where the original wedges.
@danshapiro
danshapiro merged commit 855dae7 into main Sep 20, 2026
3 checks passed
@danshapiro
danshapiro deleted the fix/cloud-vitest-tsx-stub-loop branch September 20, 2026 17:41
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