Skip to content

chore: lower the Go floor to 1.21 - #8

Merged
timzifer merged 3 commits into
mainfrom
chore/lower-go-floor
Sep 10, 2026
Merged

timzifer merged 3 commits into
mainfrom
chore/lower-go-floor

Conversation

@timzifer

@timzifer timzifer commented Sep 10, 2026 •

Copy link
Copy Markdown
Owner

go.mod said go 1.27 because that is the toolchain it was written with, which
is not a reason. For a library the directive gates who can import it, so it
should state the oldest version the code actually needs.

What the code needs

1.21 — from the clear() builtin in Params.Reset and the stdlib slices
package in one test. Nothing else in the module reaches past it, and go vet's
stdversion analyser confirms no too-new stdlib symbol slipped through.

What was holding the floor up

The dependency. golang.org/x/image requires Go 1.23 from v0.25.0 and Go 1.25
from v0.39.0, so the pin was setting the floor, not the code. Pinned to
v0.24.0, which needs only Go 1.18, and Dependabot is told not to offer the
bumps that would undo it — with the reason written next to the rule.

The downgrade is free: at a fixed toolchain, v0.24.0 rasterises
byte-identically to v0.45.0 on both Linux and Windows.

What this turned up on the way

The first CI run failed the gallery check with all twelve images changed. The
obvious suspect was the x/image downgrade. It was not — it was the Go
toolchain
: the gallery job read its version from go.mod, so lowering the
floor moved that job from Go 1.27 to Go 1.21, and the compiler is free to
contract float expressions differently between releases. Same code, same
dependency, visually identical marks, slightly different pixels.

Pinning the gallery job to the current release made it pass, which isolates the
cause. So the reproducibility this library claims is now measured more
precisely than before:

Axis Byte-identical?
Operating system (linux/macos/windows) yes
x/image version (v0.24.0 vs v0.45.0) yes
Go toolchain version (1.21 vs 1.27) no — pixels shift

That is exactly why Caps.ByteExact exists and why the suite compares float
renderers by perceptual hash rather than by bytes. The gallery check is the one
byte-exact comparison in the project, so it now pins its toolchain, and
CONTRIBUTING says so — otherwise a contributor on the floor version would
regenerate the gallery and be told it is wrong.

CI

Builds against both the floor and the current release, across all three
operating systems, and a step fails the floor leg if the matrix and go.mod
ever disagree — a declared minimum that nothing builds against is a guess.

Branch protection: the required check contexts change shape, from
test (ubuntu-latest) to test (ubuntu-latest, 1.21) and
test (ubuntu-latest, stable). Updated as part of merging this.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KwWthYNYf1egKNFrFS83Dm

timzifer and others added 3 commits September 10, 2026 08:05
go.mod said 1.27 because that happened to be the toolchain it was written with,
which is not a reason. For a library the directive is a gate on who can import
it, so it should state the oldest version the code actually needs.

That is 1.21, from the clear() builtin in Params.Reset and the stdlib slices
package in a test. Nothing else in the module reaches past it; go vet's
stdversion analyser confirms no too-new stdlib symbol slipped through.

The real constraint was the dependency. golang.org/x/image requires Go 1.23
from v0.25.0 and Go 1.25 from v0.39.0, so the pin dictated the floor. It is now
held at v0.24.0, which requires only 1.18. That costs nothing measurable:
regenerating the whole gallery against v0.24.0 produced a byte-identical
result, so the older rasteriser draws exactly what the newer one does for
everything this library asks of it. Dependabot is told not to offer the bumps
that would undo this, with the reason written next to the rule.

CI now builds against both the floor and the current release, on all three
operating systems, and a step fails the floor leg if the matrix and go.mod ever
disagree — a declared minimum that nothing builds against is a guess.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KwWthYNYf1egKNFrFS83Dm
@timzifer
timzifer merged commit 69ade5f into main Sep 10, 2026
8 checks passed
@timzifer
timzifer deleted the chore/lower-go-floor branch September 10, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant