ci(nightly): repair five job classes broken by the #649 QA hardening (#695)

Nightly has been red since 07-28; per-PR CI and main are green. Two investigations traced all five failing classes to #649: extended-matrix required AI bundles it never installs (removed), nightly SYSTEM_DEPS drifted from ci.yml (added libreoffice + a doc-binaries composite for pandoc/pdfcpu), the generated-case classifier only skipped ffmpeg (widened to pdfcpu/soffice/pandoc + excluded repo-audit specs from the lean docker image), a settings spec capped loginAttemptLimit and 429-cascaded the serial bucket (restore via API), and type-to-search refused keystrokes under a route announcer's programmatic focus (guard added). A nightly dispatch on the branch confirmed all five classes green.
This commit is contained in:
SnapOtter
2026-07-31 02:09:39 +08:00
committed by GitHub
parent 44b1aa9767
commit 1b41da7615
9 changed files with 167 additions and 17 deletions
@@ -2,8 +2,35 @@ import { describe, expect, it } from "vitest";
import {
featureUnavailableDisposition,
GeneratedCaseAccounting,
isEngineUnavailableFailure,
} from "../../helpers/generated-case-accounting.js";
describe("isEngineUnavailableFailure", () => {
// The lean docker test image skips binary-gated tools by design, so every
// spawn engine gates the same way ffmpeg does: a missing binary is a skip,
// not a product failure. A real crash (exit code + stderr) still fails.
it.each([
"ffmpeg binary not found (set FFMPEG_PATH or install ffmpeg)",
"pdfcpu binary not found (set PDFCPU_PATH or install pdfcpu)",
"soffice binary not found (set SOFFICE_PATH or install LibreOffice)",
])("treats a missing-binary message as engine-unavailable: %s", (message) => {
expect(isEngineUnavailableFailure(new Error(message))).toBe(true);
});
it.each(["spawn pandoc ENOENT", "spawn /usr/local/bin/pdfcpu ENOENT", "spawn soffice ENOENT"])(
"treats a spawn ENOENT for a known engine as engine-unavailable: %s",
(message) => {
expect(isEngineUnavailableFailure(new Error(message))).toBe(true);
},
);
it("keeps a real processing crash a failure", () => {
expect(
isEngineUnavailableFailure(new Error("pdfcpu exited with code 1: invalid page range")),
).toBe(false);
});
});
describe("GeneratedCaseAccounting", () => {
it("fails a tool that executes no generated cases", () => {
const accounting = new GeneratedCaseAccounting("resize");
@@ -70,12 +70,16 @@ describe("generated QA harness contract", () => {
expect(text).not.toContain("describe.skip(");
});
it("the actual nightly extended lane requires installed AI features", () => {
it("the nightly extended lane does not require AI features it never installs", () => {
// Strict required-AI mode (absence of a bundle is a failure) is only valid
// on a host with bundles installed, which is the release-QA fleet. The
// extended-matrix lane has no bundle-install step, so requiring them there
// 501s every installed-contract case on a bundle-less runner.
const workflow = readFileSync(join(process.cwd(), ".github/workflows/nightly.yml"), "utf8");
const extendedLane = workflow.slice(
workflow.indexOf(" extended-matrix:"),
workflow.indexOf(" api-fuzz:"),
);
expect(extendedLane).toContain('REQUIRE_AI_FEATURES: "1"');
expect(extendedLane).not.toContain("REQUIRE_AI_FEATURES");
});
});