Getting Go modules to work with nested GitLab groups

Featured image for sharing metadata for article

While trying to test for How to publish a v2 version of a Go library, I found some issues with trying to import the new Go module I was testing with.

Via Import private go modules from gitlab and the upstream issue on GitLab, it appears that this is unfortunately a long-standing known issue with GitLab.

In the below example, we're going to use a very straightforward Go module that outputs a greeting, which is packages in both a public and private Go module. Although the private module is a private repo, the code is exactly the same as the public repo, just with a different module import path.

Public repo, v0/v1

When using a public repo pre-v2, this works as can be expected:

Consuming module's code
module example

go 1.20

require gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2 v1.0.2
package main

import (
	"fmt"

	"gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/pkg"
)

func main() {
	fmt.Println(pkg.Greeting())
}

Public repo, v2+

Now, when we bump the major version of the module:

Consuming module's code
module example

go 1.20

require gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2 v2.0.0
package main

import (
	"fmt"

	"gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2/pkg"
)

func main() {
	fmt.Println(pkg.Greeting())
}

This results in the following error:

$ go mod tidy
go: downloading gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2 v2.0.0
go: example imports
        gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2/pkg: gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2@v2.0.0: verifying module: gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2@v2.0.0: reading https://sum.golang.org/lookup/gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2@v2.0.0: 404 Not Found
        server response: not found: gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2@v2.0.0: invalid version: unknown revision v2.0.0

To fix it, we need to use replace directives in our go.mod:

module example

go 1.20

require gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2 v2.0.0

replace gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2 => gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module.git/v2 v2.0.0

After this, we can then use the new version of the code.

Private repo, v0/v1

When using the private module:

Consuming module's code
module example

go 1.20

require gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module v1.0.3
package main

import (
	"fmt"

	"gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module/pkg"
)

func main() {
	fmt.Println(pkg.Greeting())
}

This ends up with the following error:

% go mod tidy
go: downloading gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module v1.0.3
go: example imports
        gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module/pkg: reading gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module/go.mod at revision private-gitlab-subgroup-go/private-module/v1.0.3: git ls-remote -q origin in /home/jamie/go/pkg/mod/cache/vcs/598c10ef3c007f61df2dc7d33cb3a4dd1f38a94496576f32b1e46abe4c66802f: exit status 128:
        remote:
        remote: ========================================================================
        remote:
        remote: ERROR: The project you were looking for could not be found or you don't have permission to view it.

        remote:
        remote: ========================================================================
        remote:
        fatal: Could not read from remote repository.

        Please make sure you have the correct access rights
        and the repository exists.

Note that this is even with the following ~/.gitconfig settings:

[url "ssh://git@gitlab.com/"]
	insteadOf = https://gitlab.com/

And with specifying GOPRIVATE:

export GOPRIVATE=gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/*

To make it work, we also need to use the following replace directive:

 module example

 go 1.20

 require gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module v1.0.4
+
+replace gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module => gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module.git v1.0.4

Private repo, v2+

Using a module that's past v1 is a little more awkward, and requires your git config, GOPRIVATE and replace directives in place:

Consuming module's code
module example.com

go 1.20

require gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module/v2 v2.0.0

replace gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module/v2 => gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/private-module.git/v2 v2.0.0
package main

import (
	"fmt"

	"gitlab.com/tanna.dev/jvt.me-examples/private-gitlab-subgroup-go/module/v2/pkg"
)

func main() {
	fmt.Println(pkg.Greeting())
}

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#blogumentation #go #gitlab.

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.