Ctrl K
ComunidadGuías…

test/scripts/required-checks.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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);
    }
  });
});