test: speed up vitest launcher startup

This commit is contained in:
Peter Steinberger
2026-04-05 13:01:37 +01:00
parent 6f5ba51f74
commit 074af3f40e
7 changed files with 92 additions and 29 deletions

View File

@@ -75,6 +75,7 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
- The shared Vitest config also fixes `isolate: false` and uses the non-isolated runner across the root projects, e2e, and live configs.
- The root UI lane keeps its `jsdom` setup and optimizer, but now runs on the shared non-isolated runner too.
- `pnpm test` inherits the same `threads` + `isolate: false` defaults from the root `vitest.config.ts` projects config.
- The shared `scripts/run-vitest.mjs` launcher now also adds `--no-maglev` for Vitest child Node processes by default to reduce V8 compile churn during big local runs. Set `OPENCLAW_VITEST_ENABLE_MAGLEV=1` if you need to compare against stock V8 behavior.
- Fast-local iteration note:
- `pnpm test:changed` runs the native projects config with `--changed origin/main`.
- `pnpm test:max` and `pnpm test:changed:max` keep the same native projects config, just with a higher worker cap.

View File

@@ -1008,13 +1008,13 @@
"runtime-sidecars:gen": "node --import tsx scripts/generate-runtime-sidecar-paths-baseline.ts --write",
"stage:bundled-plugin-runtime-deps": "node scripts/stage-bundled-plugin-runtime-deps.mjs",
"start": "node scripts/run-node.mjs",
"test": "vitest run --config vitest.config.ts",
"test": "node scripts/run-vitest.mjs run --config vitest.config.ts",
"test:all": "pnpm lint && pnpm build && pnpm test && pnpm test:e2e && pnpm test:live && pnpm test:docker:all",
"test:auth:compat": "node scripts/run-vitest.mjs run --config vitest.gateway.config.ts src/gateway/server.auth.compat-baseline.test.ts src/gateway/client.test.ts src/gateway/reconnect-gating.test.ts src/gateway/protocol/connect-error-details.test.ts",
"test:build:singleton": "node scripts/test-built-plugin-singleton.mjs",
"test:bundled": "node scripts/run-vitest.mjs run --config vitest.bundled.config.ts",
"test:changed": "vitest run --config vitest.config.ts --changed origin/main",
"test:changed:max": "OPENCLAW_VITEST_MAX_WORKERS=8 vitest run --config vitest.config.ts --changed origin/main",
"test:changed": "node scripts/run-vitest.mjs run --config vitest.config.ts --changed origin/main",
"test:changed:max": "OPENCLAW_VITEST_MAX_WORKERS=8 node scripts/run-vitest.mjs run --config vitest.config.ts --changed origin/main",
"test:channels": "node scripts/run-vitest.mjs run --config vitest.channels.config.ts",
"test:contracts": "pnpm test:contracts:channels && pnpm test:contracts:plugins",
"test:contracts:channels": "node scripts/run-vitest.mjs run --config vitest.contracts.config.ts --maxWorkers=1 src/channels/plugins/contracts",
@@ -1043,7 +1043,7 @@
"test:extensions:memory": "node scripts/profile-extension-memory.mjs",
"test:fast": "node scripts/run-vitest.mjs run --config vitest.unit.config.ts",
"test:force": "node --import tsx scripts/test-force.ts",
"test:gateway": "vitest run --config vitest.gateway.config.ts",
"test:gateway": "node scripts/run-vitest.mjs run --config vitest.gateway.config.ts",
"test:gateway:watch-regression": "node scripts/check-gateway-watch-regression.mjs",
"test:install:e2e": "bash scripts/test-install-sh-e2e-docker.sh",
"test:install:e2e:anthropic": "OPENCLAW_E2E_MODELS=anthropic bash scripts/test-install-sh-e2e-docker.sh",
@@ -1053,7 +1053,7 @@
"test:live:cache": "bun scripts/check-live-cache.ts",
"test:live:gateway-profiles": "node scripts/test-live.mjs -- src/gateway/gateway-models.profiles.live.test.ts",
"test:live:models-profiles": "node scripts/test-live.mjs -- src/agents/models.profiles.live.test.ts",
"test:max": "OPENCLAW_VITEST_MAX_WORKERS=8 vitest run --config vitest.config.ts",
"test:max": "OPENCLAW_VITEST_MAX_WORKERS=8 node scripts/run-vitest.mjs run --config vitest.config.ts",
"test:parallels:linux": "bash scripts/e2e/parallels-linux-smoke.sh",
"test:parallels:macos": "bash scripts/e2e/parallels-macos-smoke.sh",
"test:parallels:npm-update": "bash scripts/e2e/parallels-npm-update-smoke.sh",
@@ -1065,7 +1065,7 @@
"test:perf:profile:main": "node scripts/run-vitest-profile.mjs main",
"test:perf:profile:runner": "node scripts/run-vitest-profile.mjs runner",
"test:sectriage": "node scripts/run-vitest.mjs run --config vitest.gateway.config.ts && node scripts/run-vitest.mjs run --config vitest.unit.config.ts --exclude src/daemon/launchd.integration.test.ts --exclude src/process/exec.test.ts",
"test:serial": "OPENCLAW_VITEST_MAX_WORKERS=1 vitest run --config vitest.config.ts",
"test:serial": "OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs run --config vitest.config.ts",
"test:startup:bench": "node --import tsx scripts/bench-cli-startup.ts",
"test:startup:bench:check": "node scripts/test-cli-startup-bench-budget.mjs",
"test:startup:bench:save": "node --import tsx scripts/bench-cli-startup.ts --preset all --runs 5 --warmup 1 --output .artifacts/cli-startup-bench-all.json",
@@ -1074,7 +1074,7 @@
"test:startup:memory": "node scripts/check-cli-startup-memory.mjs",
"test:ui": "pnpm lint:ui:no-raw-window-open && pnpm --dir ui test",
"test:voicecall:closedloop": "node scripts/test-voicecall-closedloop.mjs",
"test:watch": "vitest --config vitest.config.ts",
"test:watch": "node scripts/run-vitest.mjs --config vitest.config.ts",
"tool-display:check": "node --import tsx scripts/tool-display.ts --check",
"tool-display:write": "node --import tsx scripts/tool-display.ts --write",
"ts-topology": "node --import tsx scripts/ts-topology.ts",

View File

@@ -24,6 +24,7 @@ function buildCmdExeCommandLine(command, args) {
export function resolvePnpmRunner(params = {}) {
const pnpmArgs = params.pnpmArgs ?? [];
const nodeArgs = params.nodeArgs ?? [];
const npmExecPath = params.npmExecPath ?? process.env.npm_execpath;
const nodeExecPath = params.nodeExecPath ?? process.execPath;
const platform = params.platform ?? process.platform;
@@ -32,7 +33,7 @@ export function resolvePnpmRunner(params = {}) {
if (typeof npmExecPath === "string" && npmExecPath.length > 0 && isPnpmExecPath(npmExecPath)) {
return {
command: nodeExecPath,
args: [npmExecPath, ...pnpmArgs],
args: [...nodeArgs, npmExecPath, ...pnpmArgs],
shell: false,
};
}

View File

@@ -1,26 +1,45 @@
import { spawnPnpmRunner } from "./pnpm-runner.mjs";
const forwardedArgs = process.argv.slice(2);
const TRUTHY_ENV_VALUES = new Set(["1", "true", "yes", "on"]);
if (forwardedArgs.length === 0) {
console.error("usage: node scripts/run-vitest.mjs <vitest args...>");
process.exit(1);
function isTruthyEnvValue(value) {
return TRUTHY_ENV_VALUES.has(value?.trim().toLowerCase() ?? "");
}
const child = spawnPnpmRunner({
pnpmArgs: ["exec", "vitest", ...forwardedArgs],
env: process.env,
});
child.on("exit", (code, signal) => {
if (signal) {
process.kill(process.pid, signal);
return;
export function resolveVitestNodeArgs(env = process.env) {
if (isTruthyEnvValue(env.OPENCLAW_VITEST_ENABLE_MAGLEV)) {
return [];
}
process.exit(code ?? 1);
});
child.on("error", (error) => {
console.error(error);
process.exit(1);
});
return ["--no-maglev"];
}
function main(argv = process.argv.slice(2), env = process.env) {
if (argv.length === 0) {
console.error("usage: node scripts/run-vitest.mjs <vitest args...>");
process.exit(1);
}
const child = spawnPnpmRunner({
pnpmArgs: ["exec", "vitest", ...argv],
nodeArgs: resolveVitestNodeArgs(env),
env,
});
child.on("exit", (code, signal) => {
if (signal) {
process.kill(process.pid, signal);
return;
}
process.exit(code ?? 1);
});
child.on("error", (error) => {
console.error(error);
process.exit(1);
});
}
if (import.meta.main) {
main();
}

View File

@@ -245,12 +245,15 @@ describe("test scripts", () => {
};
expect(pkg.scripts?.["test:serial"]).toBe(
"OPENCLAW_VITEST_MAX_WORKERS=1 vitest run --config vitest.config.ts",
"OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs run --config vitest.config.ts",
);
expect(pkg.scripts?.["test:fast"]).toBe(
"node scripts/run-vitest.mjs run --config vitest.unit.config.ts",
);
expect(pkg.scripts?.["test:gateway"]).toBe("vitest run --config vitest.gateway.config.ts");
expect(pkg.scripts?.["test"]).toBe("node scripts/run-vitest.mjs run --config vitest.config.ts");
expect(pkg.scripts?.["test:gateway"]).toBe(
"node scripts/run-vitest.mjs run --config vitest.gateway.config.ts",
);
expect(pkg.scripts?.["test:single"]).toBeUndefined();
});
});

View File

@@ -22,6 +22,28 @@ describe("resolvePnpmRunner", () => {
});
});
it("prepends node args when launching pnpm through node", () => {
expect(
resolvePnpmRunner({
npmExecPath: "/home/test/.cache/node/corepack/v1/pnpm/10.32.1/bin/pnpm.cjs",
nodeArgs: ["--no-maglev"],
nodeExecPath: "/usr/local/bin/node",
pnpmArgs: ["exec", "vitest", "run"],
platform: "linux",
}),
).toEqual({
command: "/usr/local/bin/node",
args: [
"--no-maglev",
"/home/test/.cache/node/corepack/v1/pnpm/10.32.1/bin/pnpm.cjs",
"exec",
"vitest",
"run",
],
shell: false,
});
});
it("falls back to bare pnpm on non-Windows when npm_execpath is missing", () => {
expect(
resolvePnpmRunner({

View File

@@ -0,0 +1,17 @@
import { describe, expect, it } from "vitest";
import { resolveVitestNodeArgs } from "../../scripts/run-vitest.mjs";
describe("scripts/run-vitest", () => {
it("adds --no-maglev to vitest child processes by default", () => {
expect(resolveVitestNodeArgs({ PATH: "/usr/bin" })).toEqual(["--no-maglev"]);
});
it("allows opting back into Maglev explicitly", () => {
expect(
resolveVitestNodeArgs({
OPENCLAW_VITEST_ENABLE_MAGLEV: "1",
PATH: "/usr/bin",
}),
).toEqual([]);
});
});