test/scripts/required-checks.test.ts
Rama main · réplica de lectura del repositorio original.
import { expect } from "@std/expect";
import { describe, it as test } from "@std/testing/bdd";
import * as v from "valibot";
import {
driftFindings,
manifestSchema,
requiredContexts,
runRequiredChecksCheck,
} from "#scripts/required-checks/run.ts";
/** The branch rules as the API returns them for the merge queue today. */
const liveRules = [
{ type: "creation" },
{
parameters: {
required_status_checks: [
{ context: "test", integration_id: 15368 },
{ context: "checks", integration_id: 15368 },
],
strict_required_status_checks_policy: true,
},
type: "required_status_checks",
},
{
parameters: { required_files: 1 },
type: "pull_request_files_required",
},
];
describe("required checks", () => {
test("reads the required contexts and ignores the other rules", () => {
expect(requiredContexts(liveRules)).toEqual(["checks", "test"]);
});
test("reads a ruleset with no status-check rule as an empty list", () => {
expect(requiredContexts([{ type: "creation" }])).toEqual([]);
});
test("rejects a response whose check has no context name", () => {
expect(() =>
requiredContexts([
{
parameters: { required_status_checks: [{ integration_id: 15368 }] },
type: "required_status_checks",
},
]),
).toThrow();
});
test("rejects a response that is not a list of rules", () => {
expect(() => requiredContexts({ type: "creation" })).toThrow();
});
test("finds no drift when the manifest and the ruleset agree", () => {
expect(
driftFindings({
expected: ["checks", "test"],
required: ["test", "checks"],
}),
).toEqual([]);
});
test("reports a manifest check the ruleset does not require", () => {
expect(driftFindings({ expected: ["checks"], required: [] })).toEqual([
'scripts/required-checks/checks.json [required-check]: "checks" is in the manifest but the main ruleset does not require it — add the required status check in repository Settings, or remove it from the manifest.',
]);
});
test("reports a required check the manifest does not list", () => {
expect(driftFindings({ expected: [], required: ["e2e-payments"] })).toEqual(
[
'scripts/required-checks/checks.json [required-check]: "e2e-payments" is required by the main ruleset but missing from the manifest — add it to the manifest, or remove the required status check in repository Settings.',
],
);
});
test("reports a renamed context as one missing and one extra name", () => {
const found = driftFindings({
expected: ["checks"],
required: ["unit-checks"],
});
expect(found).toHaveLength(2);
expect(found[0]).toContain('"checks"');
expect(found[1]).toContain('"unit-checks"');
});
test("passes when the ruleset requires exactly the manifest names", () => {
const lines: string[] = [];
const errors: string[] = [];
const code = runRequiredChecksCheck({
expected: ["checks", "test"],
output: {
log: (line) => lines.push(line),
logError: (line) => errors.push(line),
},
rules: liveRules,
});
expect(code).toBe(0);
expect(errors).toEqual([]);
expect(lines).toEqual([
"The main ruleset requires exactly the checks the manifest lists.",
]);
});
test("fails and names each drifted name", () => {
const errors: string[] = [];
const code = runRequiredChecksCheck({
expected: ["checks"],
output: { log: () => {}, logError: (line) => errors.push(line) },
rules: liveRules,
});
expect(code).toBe(1);
expect(errors.filter((line) => line.includes('"test"'))).toHaveLength(1);
});
test("rejects a manifest entry with no name", () => {
expect(() => v.parse(manifestSchema, ["checks", ""])).toThrow();
});
test("rejects a manifest that lists one check twice", () => {
expect(() => v.parse(manifestSchema, ["checks", "checks"])).toThrow();
});
test("records the checks the merge queue requires", async () => {
const manifest = v.parse(
manifestSchema,
JSON.parse(
await Deno.readTextFile("scripts/required-checks/checks.json"),
),
);
// Ruleset 21611101 requires the workflow jobs of test.yml: the two static
// jobs and, since the journeys became hosted evidence, the specs job. The
// list lives here because repository Settings alone is not reviewable.
expect(manifest).toEqual(["checks", "specs", "test"]);
});
test("lists no name a workflow job cannot emit", async () => {
// A manifest name no job emits would hold the merge queue for a check
// that never runs — the silent-drift class issue #2671 names. The
// live-ruleset gate holds the manifest to Settings; this holds it to the
// jobs the workflows actually declare.
const workflow = await Deno.readTextFile(".github/workflows/test.yml");
const declared = [...workflow.matchAll(/^ {2}([a-z0-9-]+):\n/gm)].map(
(match) => match[1],
);
const manifest = v.parse(
manifestSchema,
JSON.parse(
await Deno.readTextFile("scripts/required-checks/checks.json"),
),
);
for (const name of manifest) {
expect(
declared,
`"${name}" is in the manifest but test.yml declares no job named it`,
).toContain(name);
}
});
});