Speed up server CI tests (#2537)
* perf(ci): reduce server test latency Server test files use isolated resources, so they do not require suite-wide serialization. * fix(ci): scope server test parallelism to unit suite Keep real-provider and local-resource suites serialized because they may share user configuration and account limits. * fix(terminal): isolate zsh runtimes by process Prevent concurrent daemon and test processes from deleting or replacing shell integration files used by another process. * fix(ci): preserve required matrix check names GitHub evaluates job conditions before expanding a matrix. Expand active matrices first and gate their expensive steps so required check contexts are always reported. Allow superseded runs to cancel while retaining fail-open path detection.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import test from "node:test";
|
||||
|
||||
const workflowPath = new URL("../.github/workflows/ci.yml", import.meta.url);
|
||||
|
||||
function jobBlocks(source) {
|
||||
const jobs = new Map();
|
||||
let currentJob;
|
||||
|
||||
for (const line of source.split("\n")) {
|
||||
const jobMatch = /^ ([a-z0-9-]+):\s*$/.exec(line);
|
||||
if (jobMatch) {
|
||||
currentJob = jobMatch[1];
|
||||
jobs.set(currentJob, []);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentJob && (/^ \S/.test(line) || /^ \S/.test(line))) {
|
||||
jobs.get(currentJob).push(line);
|
||||
}
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
||||
test("matrix jobs expand before change gating", () => {
|
||||
const workflow = readFileSync(workflowPath, "utf8");
|
||||
const gatedMatrixJobs = [...jobBlocks(workflow)]
|
||||
.filter(([, lines]) => {
|
||||
const hasMatrix = lines.some((line) => line.startsWith(" matrix:"));
|
||||
const unsafeJobCondition = lines.some(
|
||||
(line) => line.startsWith(" if:") && line.trim() !== "if: ${{ !cancelled() }}",
|
||||
);
|
||||
return hasMatrix && unsafeJobCondition;
|
||||
})
|
||||
.map(([jobId]) => jobId);
|
||||
|
||||
assert.deepEqual(
|
||||
gatedMatrixJobs,
|
||||
[],
|
||||
"change-based job conditions skip a matrix before GitHub can emit its interpolated check names",
|
||||
);
|
||||
});
|
||||
|
||||
test("change gating allows superseded workflow runs to cancel", () => {
|
||||
const workflow = readFileSync(workflowPath, "utf8");
|
||||
const cancellationBlockingJobs = [...jobBlocks(workflow)]
|
||||
.filter(([, lines]) => lines.some((line) => line.trim().startsWith("${{ always()")))
|
||||
.map(([jobId]) => jobId);
|
||||
|
||||
assert.deepEqual(
|
||||
cancellationBlockingJobs,
|
||||
[],
|
||||
"always() keeps jobs alive after concurrency cancellation; use !cancelled() for fail-open gating",
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user