go: cmd/go: get fails on gitlab subgroups due to go-import meta tags referring to nonexistent repos
What version of Go are you using (go version
)?
$ go version go version go1.13 darwin/amd64
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/umputun/Library/Caches/go-build" GOENV="/Users/umputun/Library/Application Support/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/umputun/go-home" GOPRIVATE="" GOPROXY="direct" GOROOT="/usr/local/Cellar/go/1.13/libexec" GOSUMDB="off" GOTMPDIR="" GOTOOLDIR="/usr/local/Cellar/go/1.13/libexec/pkg/tool/darwin_amd64" GCCGO="gccgo" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="/Users/umputun/tmp/t/go.mod" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/fx/rzs1_n8137qfktxcbt_2v8pc0000gp/T/go-build570104617=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
- Created a public project on gitlab https://gitlab.com/umputuntests/sub/example with a module gitlab.com/umputuntests/sub/example
- Tried to get it, i.e.
go get -v gitlab.com/umputuntests/sub/example
- go get failed
get "gitlab.com/umputuntests/sub/example": found meta tag get.metaImport{Prefix:"gitlab.com/umputuntests/sub/example", VCS:"git", RepoRoot:"https://gitlab.com/umputuntests/sub/example.git"} at //gitlab.com/umputuntests/sub/example?go-get=1
get "gitlab.com/umputuntests/sub": found meta tag get.metaImport{Prefix:"gitlab.com/umputuntests/sub", VCS:"git", RepoRoot:"https://gitlab.com/umputuntests/sub.git"} at //gitlab.com/umputuntests/sub?go-get=1
go: finding gitlab.com/umputuntests/sub/example v0.0.2
go: downloading gitlab.com/umputuntests/sub/example v0.0.2
go: extracting gitlab.com/umputuntests/sub/example v0.0.2
go get gitlab.com/umputuntests/sub/example: git ls-remote -q https://gitlab.com/umputuntests/sub.git in /Users/umputun/go-home/pkg/mod/cache/vcs/410d993df4daac0579ff6b4402c511af12bd3d00851d05ab6183293d03664961: exit status 128:
fatal: could not read Username for 'https://gitlab.com': terminal prompts disabled
Confirm the import path was entered correctly.
If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.
What did you expect to see?
with prev versions of go (1.12.x) it works file:
go get -v gitlab.com/umputuntests/sub/example
Fetching https://gitlab.com/umputuntests/sub/example?go-get=1
Parsing meta tags from https://gitlab.com/umputuntests/sub/example?go-get=1 (status code 200)
get "gitlab.com/umputuntests/sub/example": found meta tag get.metaImport{Prefix:"gitlab.com/umputuntests/sub/example", VCS:"git", RepoRoot:"https://gitlab.com/umputuntests/sub/example.git"} at https://gitlab.com/umputuntests/sub/example?go-get=1
go: finding gitlab.com/umputuntests/sub/example v0.0.2
go: finding github.com/stretchr/testify v1.3.0
go: finding github.com/stretchr/objx v0.1.0
go: finding github.com/davecgh/go-spew v1.1.0
go: finding github.com/pmezard/go-difflib v1.0.0
go: downloading gitlab.com/umputuntests/sub/example v0.0.2
go: extracting gitlab.com/umputuntests/sub/example v0.0.2
gitlab.com/umputuntests/sub/example/strategy
gitlab.com/umputuntests/sub/example
additional notes
I think this is both gitlab problem and go 1.13 change. Gitlab seems to return go-import
tag on the parent, which doesn’t exist and this seems to confuse “go get”, trying to check module’s parent.
curl "https://gitlab.com/umputuntests/sub?go-get=1"
<html><head><meta name="go-import" content="gitlab.com/umputuntests/sub git https://gitlab.com/umputuntests/sub.git" /></head></html>
In fact, gitlab returns good-looking go-import
on any random path, for example:
curl "https://gitlab.com/random/xyz/something?go-get=1"
<html><head><meta name="go-import" content="gitlab.com/random/xyz git https://gitlab.com/random/xyz.git" /></head></html>
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 20
- Comments: 74 (32 by maintainers)
Links to this issue
Commits related to this issue
- cmd/go/internal/modfetch: report the module path for errors in (*codeRepo).Versions Updates #34094 Change-Id: Ifd10b51c2b4ebe77c4f8f68726e411f54c13b9c9 Reviewed-on: https://go-review.googlesource.co... — committed to golang/go by bcmills 5 years ago
- cmd/go/internal/modfetch/codehost: treat nonexistent repositories as “not found” If a go-import directive refers to a nonexistent repository, today we treat that as an error fetching a module that ac... — committed to golang/go by bcmills 5 years ago
- cmd/go: suppress errors in package-to-module queries if the package is already found In CL 173017, I changed the package-to-module query logic to query all possible module paths in parallel in order ... — committed to golang/go by bcmills 5 years ago
- [release-branch.go1.13] cmd/go: suppress errors in package-to-module queries if the package is already found In CL 173017, I changed the package-to-module query logic to query all possible module pat... — committed to golang/go by bcmills 5 years ago
@xavivars, this has already been fixed at head and backported to the 1.13 branch. It will be included in Go 1.13.3.
Just tested the latest build on
release-branch.go1.13
and can confirm it works with a private GitLab subgroup.@umputun, note that if the module is already in the build list, we don’t bother searching all possible paths for it. So one workaround, if you already know the module or repo path, is to simply run something like
in order to prime the appropriate paths before running any remaining
go get
subcommands.I’m still facing this issue with
go version go1.13.3 darwin/amd64
@umputun and others: this should be fixed at head and on
release-branch.go1.13
. Could someone with access to a private GitLab subgroup please try a build fromrelease-branch.go1.13
and confirm?(The instructions are here, but instead of
git checkout master
you’ll want to rungit checkout release-branch.go1.13
.)Yeah, given the timeframe for fixes to the serving paths we should probably just do that.
(I’m not particularly happy about burying errors in general, but it seems like the least-unpleasant solution here.)
Is there a reason we can’t do the module search in parallel but still walk the results in reverse order of specificity, thus ignoring errors unless every path had an error?
The permissions argument seems like a pretty distant edge case. In general, Go assumes one module path means one source code repository. If you were to return different results based on user identity, you could do that at the git layer in the same way you might at the
?go-get=
resolution layer. Either way, you’re seriously breaking the Go view of the world, and you’ll probably know you are, but have deliberately decided to take on any pain associated with differing code results.The way things are now implemented, that potential for pain for offenders now becomes real pain for anybody who relied on the more obvious behavior before, including indirectly, as in the case of those simply using these version control systems.
@TheDiveO We had a similar problem, we solved it by using the
replace
directive. For example:However please be aware that this solution does not work cleanly when trying to upgrade that said package to non-tagged versions, for example you would need to do something like:
Which then will fail with a message similar to:
We literally have to copy
vXYZ-somecommithash
, manually editgo.mod
and then overwrite that value, changing it to something likedoesn’t work with 1.12 either
go version go1.12.12 linux/amd64, from
golang:1.12
container:However with ~/.netrc everyting seems to work (1.13.3):
So, looks like .gitconfig insteadOf doesn’t play well with go mods, but .netrc is fine.
No, I didn’t but tried it now with similar setup -
commons
group public,pkg
subgroup public andsyncs
repo private (internal in gitlab’s permissions). I see very similar results:Not sure if important, but to access private repos from go I use insteadOf rewrite:
I’ve just tried with Go 1.13.3 but I still failed in
go get
my subgroup repository.P.S. My repository is a private repository. I don’t know if it is a matter or not.
@gopherbot, please backport to 1.13: this is a regression, and prevents previously-working modules from being fetched.
I’m running into issues with GitLab subgroups as well, but I’m getting a different error:
It almost seems like it’s assuming that the second part of the path must be the project. Going back to 1.12 fixes it.
Edit: Nevermind, re-ran it with
-v
and it’s the same issue mentioned above with GitLab returning the parent.it can not work as expected.
@yookoala, you probably need to configure a
git
credential helper, or add a.netrc
file containing credentials. (Thego
command is not intended to prompt for interactive logins.)See https://git-scm.com/docs/gitcredentials and #29953.
Same problems…
Thanks @bcmills and @umputun for all that context.
Our plan is to start returning a
404
in response to the first stage?go-get=1
request if the project doesn’t exist or if the user is not sufficiently authenticated. We’re tracking the issue https://gitlab.com/gitlab-org/gitlab/issues/30612. We don’t have capacity to look into this in the current development cycle, but I’ll try to have this scheduled soon. Of course, anyone from the community would also be welcome to contribute a fix too 😄@bcmills - I had a chance to test this issue with gitea. For 1.13 the situation is similar to gitlab’s, i.e. the same regression (worked with 1.12 and fails on 1.13). However, with gotip it worked fine. gitea seems to return go meta on any path, pretty much the same way as gitlab. However for those non-existing repos gitea, unlike gitlab, returns 404.
I don’t think that would be appropriate. Per RFC 2616 §10.4.2 (emphasis mine):
I can certainly make the case that we should interpret a repo 404 as “not found”, but a server that explicitly tells the
go
command to check a particular repo really should not also tell thego
command that it is not authorized to know whether that repo actually exists.At the very least, if a more RFC-compliant response code is not feasible I’d like to hear the rationale from someone at GitLab.