Skip to content

Generate with a toolchain whose flate output matches the fixtures - #2559

Open
mromaszewicz wants to merge 2 commits into
oapi-codegen:mainfrom
mromaszewicz:fix/issue-2556
Open

mromaszewicz wants to merge 2 commits into
oapi-codegen:mainfrom
mromaszewicz:fix/issue-2556

Conversation

@mromaszewicz

Copy link
Copy Markdown
Member

Fixes #2556.

Two commits: the Makefile change is 20 lines, the regeneration is 57 files of base64. Reviewing them separately is much easier than reviewing the squash.

The problem

Generated code embeds the OpenAPI spec deflate-compressed, so its base64 depends on the toolchain's compress/flate — whose output changed in Go 1.27. Regenerating on a newer toolchain rewrites the blob in ~57 committed files, and a real change is easy to miss among that noise.

The blobs currently on main were produced by Go 1.27, which is newer than the go directive allows and newer than either version CI tests, so nobody on a supported toolchain could reproduce them.

The fix

Every toolchain from the go directive through 1.26.x produces identical bytes:

toolchain blob
go1.25.0, go1.25.9, go1.26.0, go1.26.2 708092753472 (all identical)
go1.27.1 0c76b0f6ff16

So generate keeps using whatever Go is installed, and only steps down a toolchain at or past the change — to the version go.mod declares, derived from the go directive so there is nothing to keep in sync by hand.

Pinning unconditionally was the obvious move and is the wrong one: it would send everyone on a supported version to download an exact patch release they do not need, and a Makefile export overrides a GOTOOLCHAIN=local set by corporate policy, turning a policy setting into a build failure.

The second commit regenerates the fixtures to the range's bytes, so contributors on a supported Go reproduce them with their own toolchain — no pin, no download.

Verification

On a real Go 1.27.1 install:

  • make generate leaves all 58 files byte-identical.
  • The same run under GOTOOLCHAIN=local produces 0c76b0f6ff16 — matching what is committed on main today, which independently confirms those blobs came from 1.27.
  • Regenerating again restores the correct bytes, so the fallback is self-healing.

make test and make lint pass on 1.27.1 against fixtures generated at 1.25/1.26 — the decode path does not care which encoder wrote them. Every changed line in the second commit is a swaggerSpec base64 line; the decoded spec content is unchanged.

Also confirmed while investigating step 3 of the issue: nothing automated regenerates. No workflow runs make generate, and neither renovate.json nor the shared oapi-codegen/renovate-config has a postUpgradeTasks that does. The churn in 89284708 came from a maintainer regenerating by hand on a renovate branch. So no CI change is needed for this to hold.

Notes

  • There is a TODO on the fallback: it can be deleted once the go directive reaches 1.27, at which point every supported toolchain agrees again.
  • This should land promptly — any open PR whose author regenerated on 1.27 will conflict across 57 files.
  • It does not help downstream users, who get the same churn in their own generated code when they upgrade Go. Making the embedded spec encoding toolchain-independent would, but storing it uncompressed measures 5.0x larger (70 KiB → 353 KiB across these fixtures), so that deserves its own discussion rather than being folded in here.

🤖 Investigated and drafted with Claude Code.

mromaszewicz and others added 2 commits September 16, 2026 22:51
Generated code embeds the OpenAPI spec deflate-compressed, so the base64 in
every generated file depends on the toolchain's compress/flate — whose
output changed in Go 1.27. Regenerating on 1.27 or newer therefore rewrites
the blob in ~57 committed files, and the noise is easy to hide a real change
in.

Every toolchain from the `go` directive through 1.26.x produces identical
bytes, so `generate` keeps using whatever Go is installed and leaves a
GOTOOLCHAIN the environment already sets alone — pinning unconditionally
would send everyone on a supported version to download an exact patch
release they do not need, and would override a GOTOOLCHAIN=local set by
policy. Only a toolchain at or past the change is stepped down, to the
version go.mod declares, so there is nothing to keep in sync by hand.

Verified on Go 1.27.1: `make generate` reproduces the committed bytes, while
the same run under GOTOOLCHAIN=local does not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Base64 only: the embedded spec decodes to identical content. The committed
blobs had been produced by Go 1.27, which is newer than the `go` directive
allows and newer than CI tests, so nobody on a supported toolchain could
reproduce them. They now match what every toolchain from the `go` directive
through 1.26.x emits, and the Makefile steps newer ones down.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mromaszewicz
mromaszewicz requested a review from a team as a code owner September 17, 2026 05:52
@mromaszewicz mromaszewicz added the chore Any maintenance tasks that are regular, not as important to call out in the changelog label Sep 17, 2026
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The PR is not safe to merge until generation preserves an explicitly configured GOTOOLCHAIN such as local.

Findings

  1. P1 Environment Toolchain Is Overridden
Fix with agent prompt
### Issue 1
Makefile:53
When `GOTOOLCHAIN=local make generate` runs with Go 1.27 or newer, this target-specific assignment overrides `local` and forces `go1.25.0`. If the environment prohibits automatic toolchain downloads, generation fails, contrary to the stated intent to preserve policy-provided settings. Only apply the fallback when `GOTOOLCHAIN` is not already set.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

This PR makes fixture regeneration select the Go version declared by go.mod when the effective toolchain is Go 1.27 or newer, then recompresses the embedded OpenAPI specifications across generated fixtures.

  • Adds Makefile logic for detecting the effective Go toolchain and selecting a flate-compatible fallback.
  • Regenerates embedded swaggerSpec base64 data across 57 generated files.
  • Leaves generated API declarations and handler implementations unchanged.

Reviews (1) · Last reviewed commit: "chore: regenerate with the supported too..."

Comment thread Makefile
git ls-files '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && env GOBIN=$(GOBIN) make lint-ci'

ifneq ($(GO_TOOLCHAIN_FALLBACK),)
generate: export GOTOOLCHAIN := $(GO_TOOLCHAIN_FALLBACK)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Environment Toolchain Is Overridden

When GOTOOLCHAIN=local make generate runs with Go 1.27 or newer, this target-specific assignment overrides local and forces go1.25.0. If the environment prohibits automatic toolchain downloads, generation fails, contrary to the stated intent to preserve policy-provided settings. Only apply the fallback when GOTOOLCHAIN is not already set.

Prompt To Fix With AI
This is a comment left during a code review.
Path: Makefile
Line: 53

Comment:
**Environment Toolchain Is Overridden**

When `GOTOOLCHAIN=local make generate` runs with Go 1.27 or newer, this target-specific assignment overrides `local` and forces `go1.25.0`. If the environment prohibits automatic toolchain downloads, generation fails, contrary to the stated intent to preserve policy-provided settings. Only apply the fallback when `GOTOOLCHAIN` is not already set.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@jamietanna

Copy link
Copy Markdown
Member

What's the issue we're trying to fix here? We looked at this with #2536 and so use 1.27 in CI

If we're trying to make local changes easier - maybe we add a warning if we detect that we're not using Go 1.27?

@mromaszewicz

Copy link
Copy Markdown
Member Author

What's the issue we're trying to fix here? We looked at this with #2536 and so use 1.27 in CI

If we're trying to make local changes easier - maybe we add a warning if we detect that we're not using Go 1.27?

Accidental generated file churn. I don't need this to go in, it's just an idea and I'm on the fence about it. I'm happy to just use 1.27 myself. I just noticed that some regenerated files had flate churn when I was going over PR's.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Any maintenance tasks that are regular, not as important to call out in the changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Committed swaggerSpec blobs depend on the Go toolchain; pin GOTOOLCHAIN for make generate

2 participants