Skip to content

feat(test): cap test-file concurrency with GRAFT_TEST_CONCURRENCY - #681

Open
johnybradshaw wants to merge 1 commit into
trailhq:mainfrom
johnybradshaw:fix/test-concurrency-env
Open

johnybradshaw wants to merge 1 commit into
trailhq:mainfrom
johnybradshaw:fix/test-concurrency-env

Conversation

@johnybradshaw

Copy link
Copy Markdown

What

scripts/run-tests.mjs now honours an optional GRAFT_TEST_CONCURRENCY=<n> and passes --test-concurrency=<n> to node --test.

  • Unset or empty: no change. Node keeps its default of availableParallelism() - 1, so CI and every other contributor behave exactly as before.
  • Not a positive integer (0, abc, -2, 1.5): the script exits 1 with ✗ GRAFT_TEST_CONCURRENCY must be a positive integer, got '…' instead of quietly running on every core. The check runs before the run's temp folder is created, so a rejected value leaves nothing behind.

Why

Each test file gets its own Node process, and each one loads tsx. On a shared 8-vCPU dev box running several agent sessions, one npm test held load at ~20 and CPU pressure at ~78% for the whole run, and every other session on the box stalled with it. Contributors need a way to cap that without editing the script.

Verification (Node v24.21.0, Linux)

  • GRAFT_TEST_CONCURRENCY=4: sampled the runner's direct children every 2 s; there were exactly 4 test workers throughout (3–4 at the tail), against 7 by default.
  • Full suite capped (4) and uncapped: identical results both times, with the same 12 failures in each. Those 12 come from my local environment (grammar/symlink tests against a node_modules borrowed from another checkout) and don't depend on concurrency. CI is green on ae39158, the base of this branch.
  • All four invalid values exit 1, and no trail-test-run-* folder is created.

--test-concurrency needs Node ≥ 20.10. The flag is only passed when the variable is set, so engines: >=20 is unaffected.

🤖 Generated with Claude Code

npm test runs one Node process per test file, availableParallelism() - 1
at a time, each loading tsx. On a shared 8-vCPU dev box that pins every
core for the length of the run (load ~20, CPU pressure ~78%).

GRAFT_TEST_CONCURRENCY=<n> passes --test-concurrency=<n> to the runner.
Unset or empty keeps Node's default, so CI and other contributors are
unchanged. A non-positive-integer value exits 1 before the run's temp
folder is created, rather than silently falling back to all cores.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trailhq-graft

trailhq-graft Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

🌱 graft blast radius

Nothing outside this diff depends on it. 1 area changed; no indexed dependents at depth 2.
Tag: @anirudhkumar-nanonets — Test Runner · @shhdwi — Test Runner

Who knows this code — 2 people across 1 area
Area Who knows it
Test Runner · changed @anirudhkumar-nanonets — 2 commits, last 10d ago · @shhdwi — 1 commit, last yesterday

Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no @ has no GitHub handle in its commit email — tag them by hand, or add a .mailmap entry. A suggestion from history, not a CODEOWNERS rule.

Test signal per changed area — 1 –

Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.

  • – Test Runner — no function, method or class changed here

graft blast · origin/main...HEAD · depth 2 · 1 changed file

Open the interactive graph → — click an area to see its dependent symbols at file:line.

github-actions Bot added a commit that referenced this pull request Oct 23, 2026

This branch has not been deployed

No deployments
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