How can I force a specific package version using go.mod? - go

In my go.mod, I have:
...
require (
...
sigs.k8s.io/controller-runtime v0.2.0-alpha.0
)
and for some reason, when I save my files, my go.sum gets updated to include:
sigs.k8s.io/controller-runtime v0.2.0-alpha.0 h1:WM6lus3SNU4SsMlDYvjJ5fyLsG9nW3ffb/4/FpE2ZGrtnc=
sigs.k8s.io/controller-runtime v0.2.0-alpha.0/go.mod h1:HFAsYoOh6XMV+jKF1rsUjFwrknPbowfyHEHH5fRdJMf2jMX8=
sigs.k8s.io/controller-runtime v0.6.3 h1:SBbr+inLPEKhrf87vlJtrvDcwIpm+uhDvp63Bl72xYJtoOE=
sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcMs40++oyaQt4B7Cs2lEE5JYRs8vJUznj4aRP4N4JpdAY=
The first 2, I understand why they are there. However, why does the latest version (0.6.3) of the package also appear all of a sudden?
When I run, go mod tidy, I get errors suggesting that 2 files in my codebase point to packages in the latest version (0.6.3) of this package. What can I do to strictly use the 0.2.2 version in go modules + in my codebase?
go mod tidy:
<filename here> imports
sigs.k8s.io/controller-runtime/pkg/webhook/admission/builder: module sigs.k8s.io/controller-runtime#latest found (v0.6.3), but does not contain package sigs.k8s.io/controller-runtime/pkg/webhook/admission/builder

v0.2.0-alpha.0 appears to already be the version that your module is using, so you don't need to do anything to “force” it. (The version of the go command that you are using may be erroneously saving the go.sum file before it errors out. If that reproduces with the latest version — currently go1.16rc1 — please file an issue, with steps to reproduce it, at https://golang.org/issue/new .)
The error message is telling you that the go command is looking for a missing package (sigs.k8s.io/controller-runtime/pkg/webhook/admission/builder).
It is checking in the latest version of the modules that may contain that package, but the latest version (which is v0.6.3, whereas your module requires v0.2.0-alpha.0) still does not contain that package.
So the go command is telling you, essentially: “I am missing the package sigs.k8s.io/controller-runtime/pkg/webhook/admission/builder, and I cannot fix it by upgrading because v0.6.3 does not contain that package either”.

Related

Golang upgrading incompatible modules

So I have a version of chi module that is incompatible and I can't upgrade it using go get <package-name> it only upgrades to the latest incompatible version while there are quite a few more versions released. I need some functionalities from the new version library which the incompatible one does not have. The go.mod file incompatible library looks like this:
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
I tried deleting my modules and running go mod init again using, but it still gives me the incompatible version. I think this might be because my project is connected to my bitbucket repository. I also tried deleting the module from the go environment and downloading it again, but had the same outcome.
How can I overcome this problem? Does anyone have any ideas? Maybe I have to manually clear the modules from my repository as well and then try to init them again?
Thank you.
When the version you want starts to get compatible with Go modules, you have to go get the dependency and import the packages in source files with the correct versioned import path, as declared in their go.mod file.
Chi's current go.mod on master branch declares its module as:
module github.com/go-chi/chi/v5
So:
go get github.com/go-chi/chi/v5
And in source files:
import "github.com/go-chi/chi/v5"
func main() {
r := chi.NewRouter()
// ...
}

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.

Lock a specific version of a third party package in 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

`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.

`go get` : unexpected end of JSON input

What version of Go are you using (go version)?
$ go version
v1.12
The module yiigo has tag v3.0.0, but when I run go get github.com/iiinsomnia/yiigo, it gets the v2.1.0 and when I run go get github.com/iiinsomnia/yiigo#v3.0.0, it shows: go get github.com/iiinsomnia/yiigo#v3.0.0: unexpected end of JSON input
The primary issue seems to be that the v3.0.0 version of iiinsomnia/yiigo is missing the required /v3 at the end of the module line in its go.mod file:
https://github.com/iiinsomnia/yiigo/blob/v3.0.0/go.mod#L1
module github.com/iiinsomnia/yiigo <<<< wrong, missing required /v3 at end
go 1.12
require (
github.com/go-sql-driver/mysql v1.4.1-0.20190217072658-972a708cf979
...
That has since been corrected.
Because it is now a proper v3 module, the go get command should include a /v3 before the #:
module github.com/iiinsomnia/yiigo/v3#v3.2.2
From the Go modules wiki:
If the module is version v2 or higher, the major version of the module must be included as a /vN at the end of the module paths used in go.mod files (e.g., module github.com/my/mod/v2, require github.com/my/mod/v2 v2.0.0) and in the package import path (e.g., import "github.com/my/mod/v2/mypkg").
Also, it looks like a related issue was opened, with the theory being that the odd "unexpected end of JSON input" error might have come from some proxy:
https://github.com/golang/go/issues/30494
A way I've accomplished this in the past is by using git tags- for your case this should work fine.
Steps:
go get -u github.com/iiinsomnia/yiigo
cd ~/go/src/github.com/iiinsomnia/yiigo
git tag
locate tag release version you'd like to install within list
git checkout v3.0.0
go install
This will overwrite the package previously installed in your GOPATH with a new one for the specific tag version you have checked out.
Note: there is likely a better way to do this since the release of go modules.
This related post also provides alternative solutions on how to retrieve a specific version of a project's source code that may lend some help.

Resources