build: serialize test runs so concurrent agents cannot saturate the machine

Each run sized its worker pool to the whole machine, so simultaneous runs
drove the box into swap until no suite finished and tests began failing on
the 5s default timeout. Serialize runs behind a lock, cap worker counts, and
raise testTimeout. See scripts/dev/with-test-lock.mjs.
This commit is contained in:
neon
2026-08-24 04:49:55 +00:00
parent 8a30bc17aa
commit cb2ea1e898
5 changed files with 223 additions and 4 deletions
+2 -2
View File
@@ -43,9 +43,9 @@
"lint": "pnpm run lint:check",
"lint:check": "eslint \"{src,apps,libs,test}/**/*.ts\"",
"lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "vitest run --exclude test/scanner-scenarios.e2e-spec.ts --exclude test/scanner-file-operations.e2e-spec.ts",
"test": "node ../scripts/dev/with-test-lock.mjs -- vitest run --exclude test/scanner-scenarios.e2e-spec.ts --exclude test/scanner-file-operations.e2e-spec.ts",
"test:watch": "vitest",
"test:cov": "vitest run --coverage",
"test:cov": "node ../scripts/dev/with-test-lock.mjs -- vitest run --coverage",
"e2e:run": "vitest run test/app-smoke.e2e-spec.ts"
},
"dependencies": {
+8
View File
@@ -1,6 +1,12 @@
import path from 'path';
import { availableParallelism } from 'os';
import { defineConfig } from 'vitest/config';
// Concurrent agents sharing this worktree each start their own runner, and an uncapped pool
// sizes itself to the whole machine. The lock wrapper raises this for the run that holds the
// lock; anything bypassing the wrapper stays on the conservative floor.
const localMaxWorkers = Number(process.env.BO_TEST_MAX_WORKERS) || Math.max(2, Math.floor(availableParallelism() / 3));
export default defineConfig({
resolve: {
tsconfigPaths: true,
@@ -12,6 +18,8 @@ export default defineConfig({
globals: true,
environment: 'node',
pool: 'threads',
maxWorkers: process.env.CI ? undefined : localMaxWorkers,
testTimeout: 15_000,
include: ['src/**/*.test.ts', 'test/**/*.test.ts'],
passWithNoTests: true,
reporters: process.env.CI ? ['default', 'github-actions'] : ['default'],