Lock a specific version of a third party package in Go - go

Using modules, when I try to lock down a specific version of a package using the following command:
go mod edit -require "google.golang.org/grpc#v1.10.0"
It shows this under the require section in the go.mod file:
google.golang.org/protobuf v1.10.0
And then when I run:
go mod vendor
It is always pulling down the latest version which is currently v1.24.0. Under the require section in the go.mod file it shows:
google.golang.org/protobuf v1.24.0
Is there a way to lock a specific version no matter what?
I am currently using go version 1.14.3.
Thanks!

It seems that it is possible to tell go mod to only get the versions specified without bumping the version.
go -mod=readonly mod vendor
Can be found at: https://github.com/thepudds/go-module-knobs/blob/master/README.md

One way to fix this problem is do go build once you have made specific changes to go mod file. This will ensure you have go.sum file built into your codebase. This is nothing but checksum of your fetched package. By doing this, all the future pull will match the checksum of go.sum file

Related

What does "inconsistent vendoring" mean in Go?

I'm getting this inconsistent vendoring error and I'm a total Go newbie. Can anyone explain to me how go.mod interacts with vendor/modules.txt? I found this question helpful, and now I'm wondering if I should even have a vendor directory. Would that be created by running go mod vendor? I inherited this project and it already has the vendor directory in git.
Here's the relevant part of my go.mod file -
module mymodule
go 1.17
require (
gopkg.in/redis.v5 v5.2.9
)
And then the related error message:
go: inconsistent vendoring
gopkg.in/redis.v5#v5.2.9: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
In vendor/modules.txt I have:
#gopkg.in/redis.v5 v5.2.9
gopkg.in/redis.v5
gopkg.in/redis.v5/internal
gopkg.in/redis.v5/internal/consistenthash
gopkg.in/redis.v5/internal/hashtag
gopkg.in/redis.v5/internal/pool
gopkg.in/redis.v5/internal/proto
For what it's worth I'm getting this error for every dependency in my go.mod file, I just included the one about redis.
go.mod and vendor/modules.txt (if present) must be in sync.
Whenever go.mod changes and there is a vendor directory, go mod vendor needs to be run to update the contents of the vendor directory.
All direct dependencies (not marked // implicit in go.mod) are "explicit" and marked accordingly in vendor/modules.txt starting from Go 1.14.
After running go mod vendor notice the new line ## explicit added after the package reference:
#gopkg.in/redis.v5 v5.2.9
## explicit
. . .
Just to add to #rustyx's answer, in order to fix this error, I deleted the vendor folder and then I ran again go mod vendor, and the error disappeared.
For me updating the version solved the issue. I was running go1.16 and I updated to go1.18.2. Before the update I tried go mod vendor and also updating the modules.txt didn't work then, I started ignoring the vendor directory by running
go build -mod=mod to build the application or go run -mod=mod main.go to run the main.go file

How to prevent from `go build` to update the latest version of modules

I am using an open source project called "yaegi" in a large project.
I need to use older version of "yaegi": v.0.8.11, so I modified the go.mod file and replaced:
github.com/traefik/yaegi v0.9.2 // indirect with github.com/containous/yaegi v0.8.11
But when I build the project, it starts to update all the modules and replace it back to the most updated version:
root#ubuntu:~/myproj1# go build main.go
go: finding module for package github.com/traefik/yaegi/stdlib/unsafe
go: finding module for package github.com/traefik/yaegi/stdlib
go: finding module for package github.com/traefik/yaegi/interp
go: found github.com/traefik/yaegi/interp in github.com/traefik/yaegi v0.9.2
How can I prevent it and keep it using the old version v.0.8.11?
I read that according to https://tip.golang.org/cmd/go/#hdr-Maintaining_module_requirements:
The go command itself automatically updates the go.mod file to maintain a standard formatting and the accuracy of require statements.
Any go command that finds an unfamiliar import will look up the module containing that import and add the latest version of that module to go.mod automatically. […]
Any go command can determine that a module requirement is missing and must be added […].
Maybe there is a way to bypass it?
//indirect in go.mod means that at least one of your other modules you’re importing is dependent on that version of module, therefore go build shall automatically update that module, no matter how you changed that line in your go.mod. In your case if you don’t want to use yaegi module of v0.9.2 you have to first get rid of other dependencies dependent on that module from your project, and then fix your go.mod to make your project require yaegi v0.8.11. You can just delete them or make them require earlier version of yaegi by using their older version or editing their source code. Also, instead of editing go.mod directly, I’d run something like go get -v github.com/containous/yaegi#0.8.11 to checkout to a specific version of a module.

`go install` adds record in `go.mod`

I'm a bit confused about how Go modules work on installing binaries using go install.
I tried to install (https://github.com/joho/godotenv) binary by executing go install github.com/joho/godotenv/cmd/godotenv and I found out that it adds a record in the go.mod.
I'm lost as we don't use this package in the code and after running go mod tidy it gets deleted (as it is not it the code).
Can someone explain is it expected behaviour of go modules?
Secondly, how I could avoid adding it to the go.mod as we only need to install and execute the binary?
Thanks.
Go version: go version go1.13.4 darwin/amd64
Command go: The go.mod file:
The go command automatically updates go.mod each time it uses the module graph, to make sure go.mod always accurately reflects reality and is properly formatted.
The go tool will update go.mod automatically when it detects dependencies are inaccurate when performing a build.
When you install github.com/joho/godotenv/cmd/godotenv from your module, this install requires at least the package in question being built / installed (and also its dependencies, transitively).
You may safely run go mod tidy to undo the recording of this "one-time" dependency.
In general if you want to disallow the go tool to update the go.mod file, you may use the -mod=readonly flag, but that would fail go install ("can't load package: package xxx: import lookup disabled by -mod=readonly"). You can read more about this here: Go Wiki: Go modules: Can I control when go.mod gets updated and when the go tools use the network to satisfy dependencies?
Alternatively, if you want to avoid this, build / install your tools outside of your module. You may use a "dummy" module for this.

modules: how to force version of dependent lib

Overall go modules works just like the docs say. But, in one case, a dependent lib's latest tag is v1.3.0 which go mod tidy finds. However I need v1.1.0. No matter what I do (hand edit go.mod, go get -u) 'go build' merely reverts the version right back to v1.3.0 which breaks the build. Indeed, the whole point of modules is setting the dependencies: so how? Go get should set it permanently but it doesn't stay set. Using go1.13.5
No matter what I do (hand edit go.mod, go get -u) ...
After you modify the version of the dependency in the go.mod file, then what you need to do is perform go mod tidy command (from your explanation I assume you haven't done it).
Example:
# modify the dependency version on go.mod, then
go mod tidy
If you use vendoring then you also need to run the go mod vendor command to update the downloaded dependencies inside vendor/ folder.
# modify the dependency version on go.mod, then
go mod tidy
go mod vendor

go mod vendor without update to latest

I’m trying to figure out if it’s possible to run go mod vendor without the go tool updating my go.mod file.
I specifically go get package/subpackage#commit and commit my go.mod with the correct version.
Then I run go mod vendor and it automatically bumps the version of the package that I just specifically set.
I’ve looked at this page to no avail: https://github.com/golang/go/wiki/Modules#how-do-i-use-vendoring-with-modules-is-vendoring-going-away
I need to use vendor because I run a script that edits some of the vendored deps., I’m looking at the following build flow:
GO111MODULE=on go get package/subpackge#commit
GO111MODULE=on go mod vendor
./Script/patch_vendors.sh --write
GO111MODULE=off go build
My other option is modifying the copied source wherever go mod vendor donwloads it to, but
not sure how to approach that.
Thanks in advance
Per https://tip.golang.org/cmd/go/#hdr-Maintaining_module_requirements:
The go command itself automatically updates the go.mod file to maintain a standard formatting and the accuracy of require statements.
Any go command that finds an unfamiliar import will look up the module containing that import and add the latest version of that module to go.mod automatically. […]
Any go command can determine that a module requirement is missing and must be added […].
The go mod vendor command copies in all of the transitive imports of your packages and their tests, so it will automatically update the go.mod file to ensure that all of the imported packages are present.
So the problem here is likely that the commit you've selected for package/subpackage fails to provide some package that appears in the transitive imports of your program. If that is correct, you should find that go list all, go test all, and go mod tidy all make that same edit to your module's requirements.

Resources