Explicitly set go toolchain in goreleaser config #6420
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Details
We have reproducible binaries, rpms/debs and archives.
And
goreleaser.yml
holds all the knobs that can be tuned to build the binary.The only thing that affects the build and is not defined in the goreleaser config is the go toolchain version.
Currently, we set the version of the go toolchain that is used for releases in Travis:
nats-server/.travis.yml
Lines 11 to 12 in 5e60171
nats-server/.travis.yml
Line 67 in 5e60171
I spent some time trying to understand the behavior of go and toolchain directives. I think setting the toolchain used for releases in .goreleser.yml would make it more explicit and future-proof.
With this change, any human or script who has
go>1.21.0
and goreleaser installed can checkout the repo at any commit, run one command, and get binaries that will be exactly as if we were cutting a release on that commit.Several places would benefit from not having to worry about keeping toolchain and all the go build flags in sync:
https://github.com/ConnectEverything/client-tools/blob/eba999ac9a1e107205fbf89ba230df3f80458028/build-nightlies.sh#L184-L188
If we land this, we can update the above places to use
goreleaser build
, thus making sure we use exactly the same binary everywhere, and forever forget about managing/updating go versions in other places that need to build the binaryReproducible test plan
Before
Behavior is not hermetic. We depend on toolchain that happens to be installed on the build host.
Local go(`1.21.0`) < one that is specified in go.mod. Go will download and use toolchain from go.mod:
Local go(`1.23.3`) > one that is specified in go.mod. Local toolchain will be used:
After
Local go version (1.23.4) did not affevt what was used for the binary
It will download (just like it downloads all the modules)
the version of the toolchain specified in goreleaer config, and use it for building the binary.
Any go >= go1.21.0 (released 2023-08-08) will build exactly the same binary:
To build using specific toolchain one would set the
GORELEASER_TOOLCHAIN
env variable:Note that starting from go1.24.0 we can use the tool directive in go.mod, and even version goreleaser itself. It will look something like this: