Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: build fetches a module that has been replaced #27859

Closed
pokstad opened this issue Sep 25, 2018 · 13 comments

Comments

Projects
None yet
10 participants
@pokstad
Copy link

commented Sep 25, 2018

What version of Go are you using (go version)?

go version go1.11 linux/amd64

Does this issue reproduce with the latest release?

Yes, if latest release is 1.11

What operating system and processor architecture are you using (go env)?

The following was created in the docker container golang:1.11 with GO111MODULE=on:

GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/go/src/my_private_project/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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build292379904=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I am using the new module functionality to handle my project dependencies. One of my dependencies has an import path that is a gopkg.in redirect URL. My corporate network does not allow gopkg.in for security reasons, so in my go.mod file I use a replace statements:

replace (
	gopkg.in/yaml.v2 v2.0.0 => github.com/go-yaml/yaml v0.0.0-20180328195020-5420a8b6744d
	gopkg.in/yaml.v2 v2.2.1 => github.com/go-yaml/yaml v0.0.0-20180328195020-5420a8b6744d
	// ... etc
)

require (
	gopkg.in/yaml.v2 v2.2.1
	// ... etc
)

My dependency graph only lists the two versions of go-yaml that I included in my replacement statements:

$ go mod graph | grep gopkg.in/yaml
my_private_project gopkg.in/yaml.v2@v2.2.1
my_private_project@v0.0.0-XXXXXXXXXXXXXX-XXXXXXXXXXXX gopkg.in/yaml.v2@v2.2.1
my_private_project@v0.0.0-XXXXXXXXXXXXXX-XXXXXXXXXXXX gopkg.in/yaml.v2@v2.0.0
github.com/spf13/viper@v1.2.0 gopkg.in/yaml.v2@v2.2.1
github.com/hashicorp/hcl2@v0.0.0-20180905152629-864f97c8ab20 gopkg.in/yaml.v2@v2.2.1
gopkg.in/yaml.v2@v2.2.1 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405
my_private_project@v0.0.0-XXXXXXXXXXXXXX-XXXXXXXXXXXX gopkg.in/yaml.v2@v2.2.1
my_private_project@v0.0.0-XXXXXXXXXXXXXX-XXXXXXXXXXXX gopkg.in/yaml.v2@v2.2.1
gopkg.in/yaml.v2@v2.0.0 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405my_private_project

When performing a module based install, the following appears in the output:

$ GO111MODULE=on go build
Fetching https://gopkg.in/yaml.v2?go-get=1
https fetch failed: Get https://gopkg.in/yaml.v2?go-get=1: dial tcp 35.196.143.184:443: i/o timeout

The other packages then compile and the executable successfully builds.

What did you expect to see?

No references to any attempt of downloading the gopkg.in/yaml project. Instead, the direct GitHub link provided in the replacement statements should be fetched instead.

What did you see instead?

The go command attempts to reach the gopkg.in/yaml URL each time a build is attempted. It causes a longer than needed build time since the fetch times out. The build succeeds, but it isn't clear why since the fetch failed.

@bcmills bcmills added this to the Go1.12 milestone Sep 25, 2018

@bcmills bcmills changed the title Mod replace statement appears to be ignored cmd/go: build fetches a module that has been replaced Sep 25, 2018

@bcmills

This comment has been minimized.

Copy link
Member

commented Sep 25, 2018

Possibly related to #26241.

@bjm88

This comment has been minimized.

Copy link

commented Sep 26, 2018

This seems like a major issue in that every save in IDE causes build and its majorly delayed to get even basic responses on syntax errors to users. Breaks the expected and loved normally very fast compiling of go for engineers. Is there any other work around or standard way to reference local packages rather than ones that need an http fetch? Having to use replace for this instead of a native way in the require statement in go.mod seems like it would be more appropriate. Regardless of general design gap perhaps, can this specific fix be considered for 1.11.1 and not wait until 1.12?

Note I'm talking about doing a replace to relative path "../common_package"

@mibes

This comment has been minimized.

Copy link

commented Sep 26, 2018

If this issue is hindering your productivity, you can consider this temporary workaround.

Include the domain name that Go is trying to fetch in your /etc/hosts file (on Linux/Mac) and point it to your local machine. So something like this for the example above:

127.0.0.1 localhost gopkg.in

Please note that this will not fix the issue, but the fetch will fail instantly which brings the build speed back to what you are used to:

https fetch failed: Get https://gopkg.in/yaml.v2?go-get=1: dial tcp [::1]:443: connect: connection refused

Keep in mind that the above change affects all network operations.

Hope this helps short term.

@bjm88

This comment has been minimized.

Copy link

commented Sep 26, 2018

Very hacky @mibes :) . but thank you for the creative solution, guess thats what I'll do for now. It would require we actually change our package module paths to some fake domain and not our own real one, so slightly disruptive, but doable temporarily

@gopherbot

This comment has been minimized.

Copy link

commented Oct 9, 2018

Change https://golang.org/cl/140860 mentions this issue: cmd/go/internal/modload: skip fetches of replaced modules in moduleInfo

@Dreamwalker666

This comment has been minimized.

Copy link

commented Oct 11, 2018

+1 just hit this exact same problem. mine for local repos with it trying to fetch from the internet without resolving the "replace" first.

@dmitris

This comment has been minimized.

Copy link
Contributor

commented Oct 18, 2018

in general it would be great (for security and network policy-related reasons) to have the following guarantee: if all your required dependencies in "external" domains (github.com, golang.org, gopkg.in etc.) have been replaced, go will not attempt any network connections to those domains but instead will just use the domain from the replacement. This way a CI system for example could check if there are any network connections to disallowed domains and if so, conclude the replacements are not complete and break the build. Or a build could be conducted in a network-sandboxed environment without any failures or slowdown from attempting to reach inaccessible and unnecessary domains (since all code is available from the replacement domains).

I know @bcmills mentoned using GOPROXY earlier in related discussions and it's likely another way to do this but would be useful to have the discussed limits of go's network "outreach" without requirement of additional "moving parts".

@stevenh

This comment has been minimized.

Copy link
Contributor

commented Oct 19, 2018

go list also seems to download too which makes our build pipeline horrifically slow.

For now we can ensure GO111MODULE isn't set to avoid this but moving forward it seems that tools that aren't explicitly doing gets should not attempt to do any of this processing.

@Dreamwalker666

This comment has been minimized.

Copy link

commented Oct 20, 2018

It should always be local processing first then remote. What happens if your in an environment with no network support at all?

@myitcv

This comment has been minimized.

Copy link
Member

commented Oct 21, 2018

@stevenh - the fix in https://go-review.googlesource.com/c/go/+/140860 will work for all of the go commands.

@stevenh

This comment has been minimized.

Copy link
Contributor

commented Oct 22, 2018

Thanks @myitcv but still seeing go list pulling data from the net on each run even with that patch e.g.

> setenv GO111MODULE on
> /usr/bin/time -h go list -e -f '{{if .TestGoFiles }}{{.ImportPath}}{{end}}' ./... > f
go: finding github.com/multiplay/go-utils/cdata latest
go: finding github.com/multiplay/go-utils latest
        1.44s real              1.88s user              1.08s sys
> unsetenv GO111MODULE
> /usr/bin/time -h go list -e -f '{{if .TestGoFiles }}{{.ImportPath}}{{end}}' ./... > f
        0.87s real              0.78s user              0.42s sys

Should I raise a separate issue to track this?

@bcmills

This comment has been minimized.

Copy link
Member

commented Oct 22, 2018

Yes, please do raise a separate issue (with steps to reproduce it).

The fix in CL 140860 addresses the known source of spurious fetches, but there may be others.

@j0hnwhyte

This comment has been minimized.

Copy link

commented Dec 25, 2018

I had the same problem, fixed by manually compiling and using the latest version of the go sdk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.