Skip to content

feat: add --shard flag to split test files across processes - #76

Open
sakib412 wants to merge 1 commit into
japa:5.xfrom
sakib412:feat/shard
Open

sakib412 wants to merge 1 commit into
japa:5.xfrom
sakib412:feat/shard

Conversation

@sakib412

@sakib412 sakib412 commented Oct 8, 2026

Copy link
Copy Markdown

Follow-up to the discussion with @thetutlage on the AdonisJS Discord about speeding up large suites in CI.

What

Adds a --shard=current/total flag that runs a deterministic subset of test files, so a large suite can be split across parallel CI jobs:

node bin/test.js --shard=1/4
node ace test --shard=1/4   # AdonisJS forwards unknown flags to bin/test.ts

The same option can be set in config through filters.shard, for example to wire it to environment variables:

configure({
  files: ['tests/**/*.spec.ts'],
  filters: { shard: { current: 1, total: 4 } },
})

How it works

  • Sharding is done at the file level inside the Planner, after the --files filter and the suites filter. Test-level filters (--tests, --tags, --groups) still apply afterwards, inside the refiner.
  • Files are spread across shards round-robin, so shard sizes differ by at most one file.
  • The file index continues across suites, so each shard gets a similar share of every suite (for example, the slow functional suite is spread out instead of landing on one shard).
  • The split is deterministic because glob results are already sorted by FilesManager. When files is a function, the order it returns is used as-is.
  • Invalid values (0/4, 5/4, 1/0, abc, 1.5/4) throw a validation error from the planner, and the process exits with code 1.

Why not in the assembler?

In CI each shard usually runs as its own job, so every shard is already its own process, and doing it in the runner keeps it usable outside AdonisJS. Spawning all shards locally in parallel could be built on top of this flag in @adonisjs/assembler later.

Changes

  • src/cli_parser.ts: register the shard string flag, plus help text, an example and a note
  • src/types.ts: new Shard type; Filters.shard and CLIArgs.shard
  • src/config_manager.ts: parse --shard into filters.shard
  • src/validator.ts: validateShardFilter
  • src/planner.ts: #applyShard, run after collecting suite files
  • Tests for round-robin splitting, the index continuing across suites, the order relative to the files filter, the CLI flag and invalid values

Testing

  • npm test (lint + full suite with c8): 73/73 passing
  • npm run typecheck: clean
  • Manual run with 2 suites and 7 files: --shard=1/3, 2/3 and 3/3 ran 3, 2 and 2 tests, with no overlap and none missing

Adds a --shard=current/total CLI flag (and filters.shard config option) to run a deterministic subset of test files. Files are distributed in round-robin order after the files filter, with the index continuing across suites.
@sakib412
sakib412 marked this pull request as ready for review October 8, 2026 09:35
@thetutlage

Copy link
Copy Markdown
Contributor

Looks great. Can you please also open another PR for the Japa and AdonisJS docs? Also, it will be nice if we can share some common npm script or CI workflow on how to run these shards in parallel.

@thetutlage thetutlage added the Type: Feature Request Request to add a new feature to the package label Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Feature Request Request to add a new feature to the package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants