Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions internal/guard/attestation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,26 @@ func TestTheReleaseNotesSayHowToCheckWhatWasDownloaded(t *testing.T) {
t.Errorf("the release notes never mention %q", want)
}
}

// BOTH commands, because they answer different questions and the notes say
// so themselves. One asks what is inside a file and needs the predicate
// type spelled out, since gh asks for build provenance unless told
// otherwise. The other asks where a Linux archive came from and must not
// carry that flag.
//
// Asking only whether the words appear was not enough, and the full
// mutation run of 2026-09-01 said so: replacing one of the two left the
// guard green, because the other still carried the phrase. That is the
// third guard in this tree to fail the same way in one run - "is this text
// in the file" stops meaning anything the day the text appears twice.
if n := strings.Count(notes, "gh attestation verify"); n < 2 {
t.Errorf("the release notes give %d attestation command(s) and there are two things to check - "+
"what is inside a file, and where a Linux archive came from", n)
}
if !strings.Contains(notes, "--predicate-type https://spdx.dev/Document/v2.3") {
t.Error("the release notes never name the predicate type, so somebody following them asks " +
"for build provenance and is told the bill of materials is not there")
}
// The binaries are still unsigned, and the notes have said so since the
// first release. Provenance is a different question and must not be read
// as an answer to that one.
Expand Down
12 changes: 11 additions & 1 deletion internal/guard/jxlladder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,18 @@ func TestJxlStillFitsWhenTheQualityIsNotTheOneTheCeilingsWereMeasuredAt(t *testi
t.Fatal(err)
}

// The sizes matter as much as the qualities, and the first version of this
// guard had too few of them. It asked 2000, 20000 and 200000, and the full
// mutation run of 2026-09-01 called it a HOLE: turning the slow road off
// left it green. Measured afterwards by sweeping, the break shows at
// quality 100 and 5000 B, where a 160x120 picture codes to 6047 B and the
// file was to be 5000 - so the rung the table picked does not fit at all.
//
// The guard was right about what it watches and short on where it looked,
// which is the same shape as O163 one file over: a measurement proves what
// its sample covers and says nothing about the gap beside it.
for _, quality := range []string{"1", "10", "70", "90", "100"} {
for _, want := range []int64{2000, 20000, 200000} {
for _, want := range []int64{2000, 5000, 20000, 60000, 200000} {
p, err := d.Generator.Plan(format.Request{
Bytes: want, Seed: 7741, Label: true,
Properties: map[string]string{"quality": quality},
Expand Down
44 changes: 42 additions & 2 deletions internal/guard/smallfixes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,49 @@ func TestTheWindowBinaryIsBuiltSomewhere(t *testing.T) {
if err != nil {
t.Skipf("the workflow is not here: %v", err)
}
if !strings.Contains(string(raw), "./cmd/tfg-gui") {
t.Error("nothing in CI builds ./cmd/tfg-gui, so it can stop compiling without a red run")
// Asked of the job that runs on every operating system, not of the file.
//
// It used to ask the file, and the full mutation run of 2026-09-01 called
// that a HOLE. Removing both builds from the platform matrix left the guard
// green, because a third build had appeared since - in the sbom job, which
// runs on Linux alone. So the substring was still there and the protection
// was gone: a window binary that stops compiling on Windows or macOS would
// have passed CI in silence, which is the whole thing this watches for.
//
// That is the failure a guard asking "is this text in the file" always has,
// and it arrives the day the text appears a second time. Nothing about the
// text changed - the tree grew a second writer of it.
const matrixJob = "\n test:\n"
at := strings.Index(string(raw), matrixJob)
if at < 0 {
t.Fatal("ci.yml has no job called test, so this guard is reading a file it does not understand")
}
// The job ends where the next one begins, at the next key on its own
// indentation.
block := string(raw)[at+1:]
if end := nextJobAfter(block); end > 0 {
block = block[:end]
}
if !strings.Contains(block, "./cmd/tfg-gui") {
t.Error("the job that runs on every operating system does not build ./cmd/tfg-gui, " +
"so the window can stop compiling on one of them without a red run.\n" +
" A build elsewhere is not the same promise - the sbom job runs on Linux alone.")
}
}

// nextJobAfter is where the job starting at the top of block ends, which is the
// next key at the same indentation. Zero when it runs to the end of the file.
func nextJobAfter(block string) int {
for i := 1; i < len(block); i++ {
if block[i-1] != '\n' {
continue
}
rest := block[i:]
if len(rest) > 2 && rest[0] == ' ' && rest[1] == ' ' && rest[2] != ' ' && rest[2] != '#' {
return i
}
}
return 0
}

// The formatter leaves nothing beside the file it settled. It writes through a
Expand Down
Loading