Explaining Go dependency bumps
The bundled tool needs Go 1.22 or newer, and git for --base. It runs go mod graph and go list -m -mod=readonly -json all on each revision, with GOWORK=off. These read go.mod files of the module and its dependencies; they don't build or run any code, and they don't change go.mod or go.sum.
1. Pick the two revisions
- In a pull request, the old side is the merge base:
git merge-base origin/main HEAD. Use the branch name only if the user asks for it. --base REFreadsgo.modandgo.sumfiles of that commit withgit archive, so uncommitted changes in the work tree are the new side. Use--old DIR --new DIRfor two checkouts.- Run it in the module root (the directory with
go.mod), or pass--new MODULE_DIR. In a repo with several modules, run it once per module whosego.modchanged.
2. Run it
go run "${CLAUDE_PLUGIN_ROOT}/scripts/whybumped.go" --base "$(git merge-base origin/main HEAD)" --new MODULE_DIR
- If the pull request says what it meant to change (a Dependabot title such as "Bump google.golang.org/grpc from 1.63.2 to 1.67.1"), pass it with
--expect google.golang.org/[email protected]. Then every other change is a WARN, including modules thatgo.modraised on its own. - Add
--format jsonto parse the result. - Dependencies must be in the module cache or downloadable from the module proxy in the environment. Don't change
GOPROXY,GOFLAGSorGONOSUMDBunless the user asks.
Exit codes
0 means no WARN (or --fail-on never). 1 means at least one WARN. 2 means the result can't be trusted: a side's go.mod is missing, empty, cut off, not a go.mod or has no go directive; go mod graph or go list -m failed (often a missing go.sum entry, an unknown version or no network); their outputs disagree; the two sides are different modules; one side has no dependencies at all; or the --base ref doesn't exist. Treat 2 as unknown, never as a pass, and show the user the error.
Report
- Start with
go-raisedif present: the old and new go line, the dependency that needs the new version and how it got into the graph. If go.mod went further than any dependency needs, say so. - Group the module changes by the "pulled in through" line: for each root module that
go.modrequires, list what it raised or added. These are the side effects of that upgrade. requestedchanges are versions onlygo.modasks for. For a// indirectmodule that's raised above what any dependency needs, say it was raised by hand or bygo get -u, and that it could stay at the needed version if the user wants a smaller change.loweredandremovedchanges say which requirer used to need the old version and where that requirer went. A lowered module is a downgrade in the build; mention it plainly.requirement-droppedmeans go.mod lost a line while the build kept the same version through another module.go mod tidydoes this when no package needs the module. If the user didn't run tidy, check that go.mod wasn't damaged.- A chain through a version that isn't selected is real: in minimal version selection, the requirements of every version in the graph count, even ones that lost to a newer version.
- Don't edit
go.modunless the user asks. If they want a smaller change, the usual fix isgo get module@versionfor the root module only, thengo mod tidy, and run the tool again.