mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
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:
@@ -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");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user