8

If a Go repository has a go.mod file in its root but also in a sub folder, how are versions of the submodule released?

By way of example, My team have been working with vault on our internal cli tool. We have ended up using:

github.com/hashicorp/vault/api <-- has a go.mod

and

github.com/hashicorp/vault/commands <-- doesn't have a go.mod so inherits from github.com/hashicorp/vault

I am trying to update vault/api to the latest version 1.3.3:

github.com/hashicorp/vault v1.3.3
github.com/hashicorp/vault/api v1.3.3

The problem is I get:

go: github.com/hashicorp/vault/api@v1.3.3: reading github.com/hashicorp/vault/api/api/go.mod at revision api/v1.3.3: unknown revision api/v1.3.3

Which I think is caused by this root module and a conflict.

Dave C
  • 7,729
  • 4
  • 49
  • 65
Rick Burgess
  • 704
  • 1
  • 5
  • 12
  • 1
    Golang nested modules are possible, but your question is about a specific issue with vault's module(s). Please rename it to reflect the actual nature of the question – Eli Bendersky Mar 09 '20 at 13:15
  • 1
    You can have sub-modules, the problem is the package you're importing doesn't and you're treating it as if it does. Your `go.mod` references *modules* (i.e. `github.com/hashicorp/vault`), but a module can contain many *packages* (i.e. `github.com/hashicorp/vault/api`, `github.com/hashicorp/vault/commands`, etc). – Adrian Mar 09 '20 at 13:22
  • @Adrian: `vault/api` is a submodule though, not just a package in `vault`. Vault has a rather complicated module structure with several submodules that are versioned separately – Eli Bendersky Mar 09 '20 at 13:23
  • @EliBendersky i understand the example was vault related, I was more interested in the general principle around a root go.mod and a submodule go.mod I'll reword the question to be more clear – Rick Burgess Mar 09 '20 at 14:26
  • @EliBendersky i have changed the question, does that make more sense? – Rick Burgess Mar 09 '20 at 14:30
  • Does my answer help? In general you should rarely need to manipulate the `go.mod` directly. Just `go get` the version of root module that you need, and it will change its dependencies to minimal required versions on its own – Eli Bendersky Mar 09 '20 at 20:13

4 Answers4

9

The versions of sub-modules aren't necessarily going lock-step with versions of parent modules. They should be treated as completely separate modules that just happen to live in the same repository / directory structure.

Check https://github.com/hashicorp/vault/releases for the official releases/tags -- Go supports hierarchical Git tags to mark versions of submodules. For example, while as of today the latest version of vault itself is 1.3.3, I only find vault/api at v1.0.4 (this is the latest tag with api/v1.0.4)

Just do a go get to get its latest version. You don't actually have to specify versions in go.mod when importing initially - the go tool will find the latest versions for you.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • 1
    Hello, thanks for your answer, I came across it after writing (my own) answer to https://stackoverflow.com/questions/64701064/golang-separate-versioning-of-multiple-modules Can I ask for a reference to docs/specs about hierarchical tags? I failed to find such, although many hints to that exist. Thanks! – agronskiy Nov 05 '20 at 21:50
  • 1
    @agronskiy: if you'll find it somewhere it will probably be here: https://github.com/golang/go/wiki/Modules – Eli Bendersky Nov 05 '20 at 23:21
  • Will have a look! – agronskiy Nov 06 '20 at 16:40
  • Today I stumbled on this hierarchical git tags thing. Does this feature has some name? I can't find it in the go module reference. Can someone point me to the documentation of this? – minzchickenflavor May 05 '21 at 08:47
0

As an addition to answers above you can use go list command to see which versions of the module are available at the moment:

go list -m -versions github.com/hashicorp/vault/api
github.com/hashicorp/vault/api v1.0.1 v1.0.2 v1.0.3 v1.0.4 v1.1.0

Or use -u flag to see which (most recent) version you can upgrade to (if any):

go list -m -u github.com/hashicorp/vault/api
github.com/hashicorp/vault/api v1.0.3 [v1.1.0]

Where v1.0.3 is your current version, and [v1.1.0] is a most recent possible version.

go list docs

eli
  • 61
  • 1
  • 2
0

A new module version may be published by pushing a tag to the repository that contains the module source code. The tag is formed by concatenating two strings: a prefix and a version.

The version is the semantic import version for the release. It should be chosen by following the rules of semantic import versioning.

The prefix indicates where a module is defined within a repository. If the module is defined at the root of the repository, the prefix is empty, and the tag is just the version. However, in multi-module repositories, the prefix distinguishes versions for different modules. The prefix is the directory within the repository where the module is defined. If the repository follows the major subdirectory pattern described above, the prefix does not include the major version suffix.

For example, suppose we have a module example.com/repo/sub/v2, and we want to publish version v2.1.6. The repository root corresponds to example.com/repo, and the module is defined in sub/v2/go.mod within the repository. The prefix for this module is sub/. The full tag for this release should be sub/v2.1.6.

Defined here: https://github.com/golang/go/wiki/Modules#publishing-a-release

Jun Zhou
  • 11
  • 1
-1

A Go Module is nothing but a collection of Go packages (Folders). Source files belonging to a package should be placed in separate folders of their own. It is a convention in Go to name this folder with the same name as the package.

Whenever you run the go get comment under any subfolders, it will update to current directory & any parent directory has a go.mod.

pilathraj
  • 59
  • 6