go-systemd
go-systemd copied to clipboard
Troubles with Go modules and version mismatches
I was just converting a project to a Go module, and was pleased to see #307 merged and v22.0.0 tagged. So I was trying to rely on the go-systemd module, but ran into an error:
github.com/coreos/go-systemd/journal: no matching versions for query "latest"
I can trigger this error with this simple program:
package main
import _ "github.com/coreos/go-systemd/journal"
func main() {}
I can fix it by changing the import to github.com/coreos/go-systemd/v22/journal
; however, that doesn't help when I try to import, say, etcd, which gives me this error:
$ go mod tidy
go: finding golang.org/x/net latest
go: finding github.com/coreos/pkg latest
go: finding github.com/tmc/grpc-websocket-proxy latest
go: finding golang.org/x/time latest
go: finding github.com/xiang90/probing latest
go: finding github.com/golang/groupcache latest
go: finding github.com/coreos/go-systemd/journal latest
go: finding github.com/coreos/go-systemd latest
example.com/try imports
go.etcd.io/etcd/embed imports
github.com/coreos/pkg/capnslog imports
github.com/coreos/go-systemd/journal: no matching versions for query "latest"
I guess this can be fixed by capnslog adding v22
to its import, but I don't think that package has been modularized, yet. Is there some other way I can get go mod
and friends to find v22 as the latest?
Thanks for the report. I fear you are hitting intrinsic UX issues with the whole Go module machinery, and I don't think there is much I can do as a maintainer of this library.
For the standalone example, see https://github.com/coreos/go-systemd/issues/320#issuecomment-552499085 which explains the Go module switch.
For the etcd case, I think you can ask the etcd maintainers to bump the dependency on their side, or stick to use the same go-systemd version they pinned.
I Add this in my go.mod
replace (
github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 latest
)
then go mod tidy, and I made it.
It will become
require (
github.com/coreos/go-systemd v0.0.0-00010101000000-000000000000 // indirect
)
For the standalone example, see #320 (comment) which explains the Go module switch.
Yes, I was aware of the switch, to Go Modules in v22.0.0, which is great. I don't know enough about modules yet, though, to properly understand the source of or reaseon this error, though.
For the etcd case, I think you can ask the etcd maintainers to bump the dependency on their side, or stick to use the same go-systemd version they pinned.
Or capnslog I guess. How do I pin the version? Or is it better to follow @jarsaccount's suggestion? I added
replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.0.0
To my go.mod
and now go mod tidy
doesn't complain anymore.
actually, i can not load this package when i use go get whih proxy url. who have good solution ?
@theory to the best of my understanding, the "versionless replace" hack should work as long as the versioned and non-versioned releases of this library have no API-breaking changes.
Looks like capnslog does not pin a version of go-systemd, etcd does, so presumably if I copy that line it will continue to work. Would be nice to have a way to say "Pin whatever version this other module pins".
For casual readers landing here, Go modules require semver-imports as explained in the official docs: https://github.com/golang/go/wiki/Modules#semantic-import-versioning.
This means that the proper way to consume this library is via versioned imports as shown in the original bug-report here and in examples: https://github.com/coreos/go-systemd/blob/2d78030078ef61b3cae27f42ad6d0e46db51b339/examples/activation/activation.go#L24
That also means that, in the future, updating to new API-breaking releases will require updating all import paths (e.g. from github.com/coreos/go-systemd/v22/foo
to github.com/coreos/go-systemd/v23/foo
, once v23 is released).
As an unfortunate side-effect of Go module design, mixing imports from modular and non-modular versions results in some pain (as shown above) and requires some hacks via replace
. This is hopefully just a transient mess which will self-resolve as soon as all consumers migrate to Go modules.
Yes, but note that I demonstrated the issue with no dependencies, using nothing more than
package main
import _ "github.com/coreos/go-systemd/journal"
func main() {}
I think the solution is to either:
-
Explicitly import the version you want:
import github.com/coreos/go-systemd/v22/journal
. This will get the proper line ingo.mod
:require github.com/coreos/go-systemd/v22 v22.0.0
-
Or use
replace
even if you have no other dependencies, so you replace all instances of the non-version-qualifiedrequire
statement with the versioned one:replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.0.0
Unfortunately that means the
require
line won't have the v22 requirement, oddly:require github.com/coreos/go-systemd v0.0.0-00010101000000-000000000000
Not sure why that is.
@theory to the best of my understanding, the import "github.com/coreos/go-systemd/journal"
above is buggy and not valid under Go module importing rules, as stated by the official documentation (emphasis mine):
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.1) and in the package import path (e.g., import "github.com/my/mod/v2/mypkg"). This includes the paths used in go get commands (e.g., go get github.com/my/mod/[email protected]. Note there is both a /v2 and a @v2.0.1 in that example. One way to think about it is that the module name now includes the /v2, so include /v2 whenever you are using the module name).)
Thus, the correct import line would be import "github.com/coreos/go-systemd/vXYZ/journal"
(with proper XYZ
version replacement).
I understand this is catching a lot of consumers off guard, as this new model is a departure from traditional importing rules.
Oooh, okay, thanks for the clarification. I guess that makes sense, as it’s more consistently explicit.
~~@dalu please note that your comment tone is overly aggressive, and your reply doesn't bring any new/relevant content to this ticket.~~ EDIT: it looks like the user got banned from GitHub and their comment removed as a whole. For anybody, in order to reduce the amount of noise here, I'll dismiss any further similar ones in the future (as this is not a discussion forum).
Anyway, just to cover the technical side once more:
- This repository has been tagged on a regular basis since years, way before gomod came and forced semver tags. Tags up to
v21
exist but gomod does not accept them. Thus the jump tov22.0.0
. - The (multiple) breaking changes at
v22.0.0
are documented in the changelog. See https://github.com/coreos/go-systemd/pull/307 for more in-depth analysis. - Other repositories like
github.com/mongodb/mongo-go-driver
do not (yet) feel the pain of versioned import because they are at major version <= 1. - If you have doubts on how gomod-style imports work, please consult the Golang official documentation. A relevant excerpt has been already quoted here in https://github.com/coreos/go-systemd/issues/321#issuecomment-566004138.
I Add this in my go.mod
replace ( github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 latest )
then go mod tidy, and I made it.
It will become
require ( github.com/coreos/go-systemd v0.0.0-00010101000000-000000000000 // indirect )
this worked for me. thanks @jarsaccount
So. How to use the latest untag version
I Add this in my go.mod
replace ( github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 latest )
then go mod tidy, and I made it.
It will become
require ( github.com/coreos/go-systemd v0.0.0-00010101000000-000000000000 // indirect )
Just for memo. If someone want use latest untag version. You can change to
replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.1.1-0.20201123092900-87511f396ae9
😂
For those who don't want to use the import directive: This is how it can be done:
go.mod file:
module foo
go 1.16
require (
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
)
some go file
import (
"context"
"github.com/coreos/go-systemd/v22/dbus"
)
...
For whatever reason I tripped over this. Adding the version in the import path is the correct solution.
import _ "github.com/coreos/go-systemd/v22/journal"