0

I recently added a feature to my Go project which might break other projects that uses it. I decided to bump a major version to this project, "A", by adding a matching git tag 2.0.0 (it was previously 1.x.x). In my other project which requires it, "B", I updated its go.mod file like so:

module gitlab.mydomain.com/namespace/B

go 1.12

require (
    gitlab.mydomain.com/namespace/A v2.0.0
)

As you can see, I specifically mentioned v2.0.0, but once I run B, the version of A is being overridden with v0.0.0-<timestamp>-<revision>.

I made sure that the tag exists in the remote.

What am I missing here?

Kludge
  • 2,653
  • 4
  • 20
  • 42

1 Answers1

2

Starting with major version 2 (v2 and beyond), you have to modify the import path, you have to add the major version as a suffix to the import path. You must import the package as:

import "gitlab.mydomain.com/namespace/A/v2"

And this must also appear in go.mod like:

require gitlab.mydomain.com/namespace/A/v2 v2.0.0

Since major versions represent incompatible changes in Semver, their import path must also differ (the same import path denotes the same dependency). This is the import compatibility rule:

If an old package and a new package have the same import path,
the new package must be backwards compatible with the old package.

Read more about it in Go Modules Wiki: Why must major version numbers appear in import paths?

And also in blog post: The Go Blog: Go Modules: v2 and Beyond

icza
  • 389,944
  • 63
  • 907
  • 827
  • I started reading the v2 doc - does it really require to make an additional copy of the entire project in `/v2/`..?! – Kludge Dec 10 '19 at 15:05
  • @Kludge: no, it just requires the `/v2` in the module name and import paths. – JimB Dec 10 '19 at 15:12
  • @Kludge That's just one versioning strategy from the versioned module's point of view. It has the benefit of being compatible with older systems that do not support modules. But it's not a requirement. If you're using modules, a simple (semver2 compatible) version tag should suffice. – icza Dec 10 '19 at 15:22
  • @JimB, that's what I've done and now I'm getting `cannot find module providing package gitlab.mydomain.com/namespace/A/v2/somepackage`, when importing from B – Kludge Dec 10 '19 at 15:23
  • @Kludge Did you rename you module to `gitlab.mydomain.com/namespace/A/v2`? – icza Dec 10 '19 at 15:24
  • @icza, "If you're using modules, a simple (semver2 compatible) version tag should suffice" - how? – Kludge Dec 10 '19 at 15:42
  • @Kludge By that I mean you may simply add a tag to your repisitory named `v2.0.0` and the go tool will recognize that point (commit) to use when you require `v2.0.0`. The `v2` folder copy (from the blog post) is a versioning strategy that also works with tools that don't know modules. – icza Dec 10 '19 at 15:47
  • @icza, But this is exactly what I've done in the first place... and then the `v2.0.0` got overridden by `v0.0.0--` – Kludge Dec 10 '19 at 15:50
  • @Kludge: are you certain you're importing `/v2` as well? That's the go1.12 behavior for trying to import a v2.0.0 package with the original import path. Have you tried go1.13 which is a little more strict with the package handling, which may highlight the error? – JimB Dec 10 '19 at 15:57
  • @Kludge As JimB wrote: you have to change your import path to end vith `/v2`, else the go tool will rewrite the required module to `v0` or `v1`. – icza Dec 10 '19 at 15:59
  • I am certain regarding `/v2`, I'll re-check though. Meanwhile I managed to work around this with `v2.0.0+incompatible` – Kludge Dec 10 '19 at 16:02
  • 1
    @Kludge And does your imported package (module) have a `go.mod` file? – icza Dec 10 '19 at 16:03
  • 2
    @Kludge It would help a lot if you could show us your concrete repos so we don't have to ask / guess everything. – icza Dec 10 '19 at 16:04
  • 1
    @Kludge See [What incompatible in go.mod mean, will it make harm?](https://stackoverflow.com/questions/57355929/what-incompatible-in-go-mod-mean-will-it-make-harm) – icza Dec 10 '19 at 16:11
  • Still trying to make it work properly. So it finds `/v2` but it cannot find its sub-packages. Just to be clear: I replaced all occurrences of the import to contain `/v2` @icza, @JimB – Kludge Dec 11 '19 at 11:53
  • `module gitlab.mydomain.com/namespace/A/v2@latest found (v2.0.0, replaced by ../A/v2/), but does not contain package gitlab.mydomain.com/namespace/A/v2/somepackage` (I'm using `replace` to work locally) – Kludge Dec 11 '19 at 11:56