diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07f37fb..8ff0801 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,14 +22,58 @@ jobs: - uses: actions/setup-go@v7 with: - go-version: '1.27.3' + # ⛔ 1.27.4 BECAUSE INSTALLING A FLEET TOOL REQUIRES IT. fleettools + # declares `go >= 1.27.4`, so 1.27.3 could not install aptneed at + # all: "requires go >= 1.27.4 (running go 1.27.3; + # GOTOOLCHAIN=local)". GOTOOLCHAIN is left alone on purpose — a + # runner that silently fetched a newer toolchain would measure one + # nobody chose — so the pin is what has to move. + # + # ⛔ SECOND OCCURRENCE IN TWO DAYS: go-pdfkit/ops hit the identical + # line on 2026-11-13. Any repository in this fleet pinning below + # 1.27.4 fails the moment it installs a fleettools command, and the + # failure names both versions, so it is at least legible. + go-version: '1.27.4' check-latest: true cache: true + # ⛔⛔ THE FOREIGN JUDGE HAD NEVER RUN ON ANY LANE. Measured on run + # 43595391186: "qpdf" appears ZERO times in the whole log, and this job + # reported `ok 0.197s` where the same suite takes 0.758s on a machine + # that has qpdf. Every test that agrees with qpdf — the sweep over 42 + # generated files, and the control that an ordinary file is REFUSED — + # skipped, and `go test` without -v says nothing about a skip, so + # nothing in the log could have told anyone. Coverage stayed at 100% + # the whole time: the same statements are reached by the tests that + # need no qpdf, so that gate cannot see this and never could. + # + # ⛔ This repository already holds the opposite standard one job down, + # about a missing qemu emulator: "A lane that reports success for an + # architecture it never ran is the one outcome this matrix exists to + # rule out." + # + # aptneed because a mirror outage must not read as a missing judge: + # go-pdfkit/ops#90 was four red runs in half an hour on a third + # party's DNS. --need is the binary, not the package: apt saying yes is + # not qpdf being on PATH. + - name: Install qpdf, the foreign judge the linearization tests print by + run: | + GOBIN=/usr/local/bin go install github.com/go-fleettools/fleettools/cmd/aptneed@latest + sudo aptneed --need qpdf qpdf + + # Printed on purpose: the version is in the log, so "which qpdf agreed" + # is answerable after the fact rather than assumed. + - name: Say which qpdf will judge + run: qpdf --version + - name: go vet run: go vet ./... + # REQUIRE_QPDF makes a missing judge FAIL here instead of skipping. It + # is set on this lane only, because this is the lane that installs it. - name: Test with coverage + env: + REQUIRE_QPDF: "1" run: go test -covermode=set -coverprofile=coverage.out ./... - name: Assert exact 100% statement coverage @@ -94,7 +138,7 @@ jobs: - uses: actions/checkout@v7 - uses: actions/setup-go@v7 with: - go-version: '1.27.3' + go-version: '1.27.4' # ⛔ `qemu-user-static` is a VIRTUAL package on Ubuntu 26.04, which # `ubuntu-latest` became on 2026-10-19, and apt refuses to choose between its # two providers: @@ -157,5 +201,5 @@ jobs: - uses: actions/checkout@v7 - uses: actions/setup-go@v7 with: - go-version: '1.27.3' + go-version: '1.27.4' - run: go test ./... diff --git a/linearized_test.go b/linearized_test.go index 960856e..c1e37c9 100644 --- a/linearized_test.go +++ b/linearized_test.go @@ -938,10 +938,43 @@ func TestCheckLinearizedAgreesWithQpdfAcrossPageCountsAndShapes(t *testing.T) { } } +// qpdfOrSkip finds the foreign judge, and REFUSES TO SKIP IT UNDER CI. +// +// ⛔⛔ IT SKIPPED EVERYWHERE, AND NOWHERE MORE QUIETLY THAN IN CI. Measured on +// run 43595391186: the word "qpdf" appears ZERO times in the whole log, and +// the suite reports `ok 0.197s` where the same suite takes 0.758s on a +// workstation that has qpdf. Every test that agrees with qpdf — the sweep +// across 42 generated files, and the negative control that an ordinary file +// is refused — has never run on any lane, and `go test` without -v prints +// nothing about a skip, so the log could not say so either. Coverage stayed +// at 100% throughout, because the same statements are reached by the tests +// that need no qpdf: that gate cannot see this and never could. +// +// ⛔ THIS REPOSITORY ALREADY HOLDS THE OPPOSITE STANDARD, one job away. Of a +// missing qemu emulator its own workflow says: "A missing emulator FAILS this +// lane. A lane that reports success for an architecture it never ran is the +// one outcome this matrix exists to rule out." A missing foreign judge is the +// same outcome for a different reason, and go-pdfkit/ops already does this +// for pdftoppm — its render tests t.Fatal when CI is set. +// +// ⛔ IT KEYS ON REQUIRE_QPDF AND NOT ON CI, because not every lane CAN run it +// and a rule that demands the impossible gets deleted. Under qemu-user the +// test binary is emulated and an `execve` of the host's x86-64 qpdf is not +// something the emulator can carry out; the Windows lane has no apt. So ONE +// lane installs qpdf and sets REQUIRE_QPDF, and on that lane a missing judge +// is a failure. The others skip, which is now a stated design rather than an +// accident nobody could see. +// +// Off CI it skips too: a contributor without qpdf should be able to run the +// suite, and that skip is visible to them because they chose it. func qpdfOrSkip(t *testing.T) string { t.Helper() path, err := exec.LookPath("qpdf") if err != nil { + if os.Getenv("REQUIRE_QPDF") != "" { + t.Fatal("REQUIRE_QPDF is set and qpdf is not installed: the foreign judge is the whole " + + "point of this test, and a lane that skips it reports success for an agreement it never checked") + } t.Skip("qpdf is not installed, so there is no independent linearizer to agree with") } return path