Skip to content

Commit 950f1e7

Browse files
killaguclaude
andcommitted
perf(ci): shard egg-bin test job to keep ubuntu ≀60s
Test bin (ubuntu) ran 108s β€” over the 60s target β€” bottlenecked by two heavy files (dev.test.ts ~49s, test.test.ts ~42s) that each spawn many egg-bin CLI subprocesses. vitest --shard hashes both into one slice, so split by explicit file groups via scripts/run-egg-bin-shard.js: `dev` and `test` run those files alone, `rest` excludes them (new files default to rest). Also export HOME=%USERPROFILE% on the windows egg-bin job, matching the main test job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c1c4edf commit 950f1e7

2 files changed

Lines changed: 73 additions & 6 deletions

File tree

β€Ž.github/workflows/ci.ymlβ€Ž

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,16 @@ jobs:
263263
matrix:
264264
os: ['ubuntu-latest', 'windows-latest']
265265
node: ['24']
266+
# dev.test.ts (~49s local) and test.test.ts (~42s) each spawn many
267+
# egg-bin CLI subprocesses; vitest --shard hashes both into one slice,
268+
# so split by explicit file groups to keep each ubuntu shard ≀60s.
269+
bin-shard: ['dev', 'test', 'rest']
266270

267-
name: Test bin (${{ matrix.os }}, ${{ matrix.node }})
271+
name: Test bin (${{ matrix.os }}, ${{ matrix.node }}, ${{ matrix.bin-shard }})
268272
runs-on: ${{ matrix.os }}
269273

270274
concurrency:
271-
group: test-egg-bin-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-(${{ matrix.os }}, ${{ matrix.node }})
275+
group: test-egg-bin-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-(${{ matrix.os }}, ${{ matrix.node }}, ${{ matrix.bin-shard }})
272276
cancel-in-progress: true
273277

274278
steps:
@@ -286,10 +290,16 @@ jobs:
286290
- name: Install dependencies
287291
run: ut install --from pnpm || (sleep 5 && ut install --from pnpm) || (sleep 10 && ut install --from pnpm)
288292

289-
- name: Run tests
290-
run: |
291-
ut run build -- --workspace ./tools/egg-bin
292-
ut run ci --workspace @eggjs/bin
293+
- name: Set HOME on Windows
294+
if: ${{ matrix.os == 'windows-latest' }}
295+
shell: pwsh
296+
run: echo "HOME=$env:USERPROFILE" >> $env:GITHUB_ENV
297+
298+
- name: Build egg-bin
299+
run: ut run build -- --workspace ./tools/egg-bin
300+
301+
- name: Run tests (bin shard ${{ matrix.bin-shard }})
302+
run: node scripts/run-egg-bin-shard.js ${{ matrix.bin-shard }}
293303

294304
- name: Code Coverage
295305
# skip on windows, it will hangup on codecov https://github.com/codecov/codecov-action/issues/1787

β€Žscripts/run-egg-bin-shard.jsβ€Ž

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Shard the @eggjs/bin (egg-bin) test suite into wall-time-balanced groups so
4+
* each CI job stays ≀60s on ubuntu.
5+
*
6+
* The two heaviest files β€” test/commands/dev.test.ts (~49s local) and
7+
* test/commands/test.test.ts (~42s) β€” each spawn many egg-bin CLI subprocesses.
8+
* vitest's hash-based --shard puts both in the same slice, so we split by
9+
* explicit positional file filters instead.
10+
*
11+
* Usage: node scripts/run-egg-bin-shard.js <dev|test|rest>
12+
*/
13+
14+
import { spawnSync } from 'node:child_process';
15+
import { existsSync } from 'node:fs';
16+
import path from 'node:path';
17+
import process from 'node:process';
18+
19+
const WORKSPACE = path.join('tools', 'egg-bin');
20+
21+
// File groups, relative to the egg-bin workspace. `rest` is expressed as
22+
// excludes so any new test file lands there by default (never silently
23+
// dropped).
24+
const SHARDS = {
25+
dev: { include: ['test/commands/dev.test.ts'] },
26+
test: { include: ['test/commands/test.test.ts'] },
27+
rest: { exclude: ['test/commands/dev.test.ts', 'test/commands/test.test.ts'] },
28+
};
29+
30+
const shardName = process.argv[2];
31+
const entry = SHARDS[shardName];
32+
if (!entry) {
33+
console.error(`usage: node scripts/run-egg-bin-shard.js <${Object.keys(SHARDS).join('|')}>`);
34+
process.exit(2);
35+
}
36+
37+
// Use the root-hoisted vitest binary with --root pointed at the egg-bin
38+
// workspace. Running `ut execute vitest` from the workspace cwd fails because
39+
// vitest is hoisted to the repo root, not duplicated into tools/egg-bin.
40+
const vitestBin = path.resolve('node_modules', '.bin', process.platform === 'win32' ? 'vitest.cmd' : 'vitest');
41+
if (!existsSync(vitestBin)) {
42+
console.error(`vitest binary not found at ${vitestBin}`);
43+
process.exit(1);
44+
}
45+
46+
const args = ['run', '--root', WORKSPACE, '--coverage', '--retry', '2'];
47+
if (entry.include) {
48+
args.push(...entry.include);
49+
} else {
50+
for (const ex of entry.exclude) {
51+
args.push('--exclude', `**/${ex}`);
52+
}
53+
}
54+
55+
console.log('[run-egg-bin-shard] shard=%s args=%j', shardName, args);
56+
const res = spawnSync(vitestBin, args, { stdio: 'inherit' });
57+
process.exit(res.status ?? 1);

0 commit comments

Comments
Β (0)