release: stop running go mod tidy at release time, assert tidiness in CI

goreleaser ran `go mod tidy` as a before-hook inside the release container.
It took v0.63.8 down: the hook spent 4m49s walking the module graph and then
failed when proxy.golang.org returned HTTP/2 INTERNAL_ERROR on six unrelated
fetches. `go mod tidy` resolves the test dependencies of dependencies too, so
it touches far more of the network than a build needs, on the one path where
a flake costs a release.

The hook was also unsound in a quieter way. It MUTATES go.mod/go.sum, so a
drifted module set would have been silently rewritten inside the container
and the published binaries built against something no CI job had ever
compiled. A release-time rewrite is not a check.

Drop it — the config already skips tests here on the reasoning that the tag
is on a green commit, and the same argument applies.

Nothing verified module tidiness before this: no workflow, no Makefile
target. So the `lint` job gains a `go mod tidy` + `git diff --exit-code`
step, which fails the PR that introduces drift instead of papering over it
at tag time. main is already tidy, so the gate is green on landing.

Verified with the real toolchain, not by reading it:

  * `goreleaser build --snapshot` with a deliberately failing before-hook
    aborts at "running before hooks" in 0s, so hooks do execute in that mode;
    with `hooks: []` the stage never appears and the run goes straight from
    snapshotting to building. No default hook takes its place.
  * `goreleaser check` validates the config.
  * The CI gate passes on main unchanged, and fails with exit 1 (naming
    go.mod) against a commit carrying a deliberately untidy require line.
This commit is contained in:
Andrey Kumanyaev
2026-08-20 21:56:42 +02:00
parent e8d60b80cc
commit ee1b77a142
2 changed files with 31 additions and 5 deletions
+15
View File
@@ -162,6 +162,21 @@ jobs:
version: v2.11.4
args: --timeout=10m
# goreleaser used to run `go mod tidy` as a release before-hook, which
# meant an untidy go.mod was silently rewritten inside the release
# container — the shipped binaries could be built against a module set
# no CI job had ever compiled. That hook is gone; tidiness is asserted
# here instead, on the PR that introduces the drift, and it FAILS rather
# than rewrites.
- name: go.mod is tidy
run: |
set -euo pipefail
go mod tidy
if ! git diff --exit-code --stat go.mod go.sum; then
echo "FATAL: go.mod/go.sum are not tidy — run \`go mod tidy\` and commit the result" >&2
exit 1
fi
build-onnx:
runs-on: ubuntu-latest
steps:
+16 -5
View File
@@ -13,11 +13,22 @@ version: 2
# release.yml once the darwin hashes exist — it is NOT generated here.
# - windows: the CGo tree-sitter bindings need a real mingw C/C++ toolchain.
before:
hooks:
- go mod tidy
# Tests run in CI on every push. Re-running ./... inside
# goreleaser-cross slows the tag-to-artifact loop without catching
# anything new — the tag is already on a green commit.
hooks: []
# No before hooks, for the same reason in both cases: the tag is already
# on a green commit, so re-running work here costs tag-to-artifact time
# without catching anything new.
#
# Tests run in CI on every push, so `go test ./...` inside
# goreleaser-cross adds nothing.
#
# `go mod tidy` was worse than redundant. It walks the full module graph
# including the test dependencies of dependencies, so it spent ~5 minutes
# on the network and took v0.63.8 down when proxy.golang.org returned
# HTTP/2 INTERNAL_ERROR on six unrelated fetches. And because it MUTATES
# go.mod/go.sum in the container, a drifted module set would be silently
# rewritten at release time and the shipped binaries built against
# something no CI job had ever compiled. Tidiness is now asserted in the
# `lint` job of ci.yml, where drift fails the PR instead.
builds:
- id: main