test(ci): double test deadlines on hosted runners (#10417)

* test(javascript): give the wide fingerprint regression a capacity deadline

Each case runs about 22 s of CPU-bound projection on a typical hosted
runner. Its explicit 30 s deadline failed on slower runners at both two
and four Vitest workers, and it also overrode the suite's 60 s
coverage-mode allowance.

* test(ci): double test deadlines on hosted runners

Hosted CI jobs run four Vitest workers on a four-core runner. CPU-bound
capacity cases then share every core with other workers and their
subprocesses; three such cases exceeded the 30 s deadline at four
workers (16.8-22.7 s at two). The deadline only needs to bound a hang,
so hosted CI doubles it: 60 s, or 120 s with coverage. Local runs keep
30 s and 60 s.

* test(ci): check worker and deadline policy for local and hosted runners

The policy test loaded vitest.config.ts in a child that inherited the
parent's GITHUB_ACTIONS, so on CI it observed the hosted deadlines and
failed. Select the runner explicitly and check both: two workers and the
base deadline locally, four workers and twice the deadline on hosted CI.
This commit is contained in:
morluto authored and GitHub committed 2026-11-13 15:17:24 -05:00
1 parent da91bbd4eb
commit cc7d73d23a
4 files changed
+54 -33

No files matched your search

+3 -1
View File
@@ -239,7 +239,9 @@ changes additionally need package verification; provider changes need actual
provider evidence.
Vitest projects use up to two workers, bounded by host parallelism. GitHub
Actions jobs own their runner and use up to four.
Actions jobs own their runner and use up to four. Test deadlines are 30 seconds,
or 60 with coverage; hosted CI doubles both because CPU-bound cases there share
every core with other workers and their subprocesses.
`process-boundary` runs later with serial files because process-tree sampling
shares host resources. Acceptance and process-global cases use isolated forks
without serial scheduling. Pure domain/service, composition, conformance,
@@ -1,5 +1,6 @@
import { execFileSync } from "node:child_process";
import { mkdir, writeFile } from "node:fs/promises";
import { availableParallelism } from "node:os";
import { join } from "node:path";
import { pathToFileURL } from "node:url";
@@ -161,34 +162,42 @@ describe("Vitest project configuration", () => {
);
});
it.each([
{ flags: [], timeout: 30_000, lines: 68 },
{ flags: ["--coverage"], timeout: 60_000, lines: 68 },
{ flags: ["--coverage.enabled"], timeout: 60_000, lines: 68 },
{ flags: ["--coverage=false"], timeout: 30_000, lines: 68 },
{
flags: ["--coverage.enabled=false"],
timeout: 30_000,
lines: 68,
},
{
flags: ["--coverage.provider=v8"],
timeout: 30_000,
lines: 68,
},
{
flags: ["--coverage.enabled", "--shard", "1/6"],
timeout: 60_000,
lines: 0,
},
{
flags: ["--coverage.enabled=false", "--shard=1/6"],
timeout: 30_000,
lines: 0,
},
])(
"resolves worker resources from actual CLI options: $flags",
async ({ flags, timeout, lines }) => {
it.each(
[
{ flags: [], timeout: 30_000, lines: 68 },
{ flags: ["--coverage"], timeout: 60_000, lines: 68 },
{ flags: ["--coverage.enabled"], timeout: 60_000, lines: 68 },
{ flags: ["--coverage=false"], timeout: 30_000, lines: 68 },
{
flags: ["--coverage.enabled=false"],
timeout: 30_000,
lines: 68,
},
{
flags: ["--coverage.provider=v8"],
timeout: 30_000,
lines: 68,
},
{
flags: ["--coverage.enabled", "--shard", "1/6"],
timeout: 60_000,
lines: 0,
},
{
flags: ["--coverage.enabled=false", "--shard=1/6"],
timeout: 30_000,
lines: 0,
},
].flatMap((policy) =>
// Hosted CI owns a four-core runner: up to four workers, doubled deadlines.
[
{ ...policy, hosted: false, workers: 2, scale: 1 },
{ ...policy, hosted: true, workers: 4, scale: 2 },
],
),
)(
"resolves worker resources from actual CLI options: $flags (hosted: $hosted)",
async ({ flags, timeout, lines, hosted, workers, scale }) => {
const root = await createTestTempDirectory("rea-vitest-worker-policy-");
const script = join(root, "worker-policy.mjs");
await writeFile(
@@ -200,6 +209,7 @@ describe("Vitest project configuration", () => {
execArgv: project.test.execArgv,
timeout: config.test.testTimeout,
lines: config.test.coverage.thresholds.lines,
workers: config.test.maxWorkers,
}));
`,
);
@@ -208,6 +218,8 @@ describe("Vitest project configuration", () => {
["--import", "tsx", script, ...flags],
{
cwd: repository,
// Select the runner explicitly; CI itself sets GITHUB_ACTIONS.
env: { ...process.env, GITHUB_ACTIONS: hosted ? "true" : "" },
timeout: 10_000,
maxBuffer: 64 * 1024,
stopSignal: "SIGTERM",
@@ -215,8 +227,9 @@ describe("Vitest project configuration", () => {
);
expect(JSON.parse(result.stdout)).toEqual({
execArgv: ["--max-old-space-size=512"],
timeout,
timeout: timeout * scale,
lines,
workers: Math.min(workers, availableParallelism()),
});
},
);
@@ -94,5 +94,8 @@ it.each(["direct", "transferred"] as const)(
});
}
},
30_000,
// About 22 s of CPU-bound projection on a typical hosted runner. A suite
// deadline of 30 s fails it on slower runners, and an explicit 30 s also
// removed the suite's longer coverage-mode allowance.
60_000,
);
+5 -2
View File
@@ -150,8 +150,11 @@ export default defineConfig({
runner: "./tests/processOwnershipRunner.ts",
// Boundary projects may compete with TypeScript, docs, and package checks
// under Turbo. Keep the deadline bounded while avoiding false failures from
// host-level CPU and filesystem contention.
testTimeout: COVERAGE_ENABLED ? 60_000 : 30_000,
// host-level CPU and filesystem contention. Hosted CI runs a worker per
// core, so CPU-bound cases share the runner with each other's subprocesses;
// the deadline still bounds a hang there, at twice the local allowance.
testTimeout:
(COVERAGE_ENABLED ? 60_000 : 30_000) * (DEDICATED_CI_RUNNER ? 2 : 1),
coverage: {
enabled: false,
provider: "v8",