Files
paseo/scripts/ci-workflow.test.mjs
Mohamed Boudra fdee3236f7 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.
2026-07-28 21:51:12 +08:00

58 lines
1.7 KiB
JavaScript

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",
);
});