Aller au contenu
login
arrow_backRetour aux issues
golang/go #80497

x/exp/cmd/gorelease: circular dependency causes incorrect analysis

ecoDébutant help wanted NeedsInvestigation

descriptionDescription

### Go version Reproducible using the latest version of go and gorelease ### Output of `go env` in your module/workspace: ```shell AR='ar' CC='gcc' CGO_CFLAGS='-O2 -g' CGO_CPPFLAGS='' CGO_CXXFLAGS='-O2 -g' CGO_ENABLED='1' CGO_FFLAGS='-O2 -g' CGO_LDFLAGS='-O2 -g' CXX='g++' GCCGO='gccgo' GO111MODULE='' GOAMD64='v1' GOARCH='amd64' GOAUTH='netrc' GOBIN='' GOCACHE='/home/jphillips/.cache/go-build' GOCACHEPROG='' GODEBUG='' GOENV='/home/jphillips/.config/go/env' GOEXE='' GOEXPERIMENT='' GOFIPS140='off' GOFLAGS='-mod=mod' GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build959380834=/tmp/go-build -gno-record-gcc-switches' GOHOSTARCH='amd64' GOHOSTOS='linux' GOINSECURE='' GOMOD='/dev/null' GOMODCACHE='/home/jphillips/go/pkg/mod' GONOPROXY='' GONOSUMDB='' GOOS='linux' GOPATH='/home/jphillips/go' GOPRIVATE='' GOPROXY='https://proxy.golang.org,direct' GOROOT='/home/jphillips/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.26.5.linux-amd64' GOSUMDB='sum.golang.org' GOTELEMETRY='local' GOTELEMETRYDIR='/home/jphillips/.config/go/telemetry' GOTMPDIR='' GOTOOLCHAIN='auto' GOTOOLDIR='/home/jphillips/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.26.5.linux-amd64/pkg/tool/linux_amd64' GOVCS='' GOVERSION='go1.26.5' GOWORK='' PKG_CONFIG='pkg-config' ``` ### What did you do? Ran `gorelease` on a branch where no API changes are present. The issue originally occurred with an internal module in a private repository. But I was able to create a minimal reproducer (attached). [repro.zip](https://github.com/user-attachments/files/30241626/repro.zip) A one line change appears to fix the issue for me: ```patch diff --git a/cmd/gorelease/gorelease.go b/cmd/gorelease/gorelease.go index e155323..7a999ac 100644 --- a/cmd/gorelease/gorelease.go +++ b/cmd/gorelease/gorelease.go @@ -1082,7 +1082,18 @@ func prepareLoadDir(ctx context.Context, modFile *modfile.File, modPath, modRoot f.AddModuleStmt("gorelease-load-module") f.AddRequire(modPath, version) if !cached { - f.AddReplace(modPath, version, modRoot, "") + // Replace all versions of modPath (not just the specific `version` + // required above) with the local module directory. A version-scoped + // replace only takes effect when minimal version selection picks that + // exact version. If the module appears in its own build graph as a + // transitive dependency at a higher version than `version` (a self + // import cycle across modules, e.g. a -> b -> a), MVS selects that higher + // version, the version-scoped replace is silently ignored, and the + // published module is loaded from the cache instead of the local + // directory. That makes the local module's API look like the older + // published version and reports spurious removals. A wildcard replace + // pins the local directory regardless of the selected version. + f.AddReplace(modPath, "", modRoot, "") } if modFile != nil { if modFile.Go != nil { ``` ### What did you see happen? `gorelease` identifies removed APIs that still exist on the current branch. ```shell > gorelease -base=v2.0.2 # example.com/m/v2 ## incompatible changes Bar: removed ``` The repro module has a transitive dependency on an older version of itself. This seems to break some of the assumptions made in `gorelease` when handling the temporary module created during analysis. Specifically, in [prepareLoadDir](https://github.com/golang/exp/blob/764159d718efdc208c8aca89cf725febea120ec1/cmd/gorelease/gorelease.go#L1055) a replace directive is added for a synthesized `v2.0.0-gorelease` release version. But the transitive circular dependency causes a higher version to win the MVS selection, resulting in the transitive version being pulled from the module cache as the "current" version rather than the local version specified in the replace directive. Explicitly passing a `-version` flag to `gorelease` that's higher than the transitive dependency version allows the MVS selection to proceed as expected. ```shell > go
codeOuvre sur GitHub