I'm working with a monorepo that is organized by language at the top level, so all Go modules are located in the go
directory in the repository root. I want to set up a vanity import URL that points to the go
directory rather than the repository root so that the go/
does not need to be included in the import path.
Current file structure:
/
go/
module1/
module2/
Desired import format:
import (
"go.example.com/module1"
"go.example.com/module2"
)
currently possible but not desired:
import (
"go.example.com/go/module1"
"go.example.com/go/module2"
)
According to the docs the format for the <meta>
element at go.example.com
should be of the form:
<meta name="go-import" content="import-prefix vcs repo-root">
So in this case I would have:
<meta name="go-import" content="go.example.com git github.com/example/repo">
This translates the path following the import-prefix
to a path relative to the root directory of the repository, so that go.example.com/this/path
looks for the this/path
directory in the repo. I would like instead for the path to be relative to the go
directory in the repo instead of the repo root.
Is there any way to inform go get
that the paths following go.example.com
should be relative to github.com/example/repo/go
rather than just github.com/example/repo
?
CodePudding user response:
Not directly, but there are workarounds.
From this issue in golang/go:
[...] there is currently no way for the HTTPS server to indicate that the module is offset by the prefix
src/go
, since that is not a part of the Go package path. This layout is just not going to work with thego
command's built-ingit
support.
With the go
command's built-in git
support, import specs start with the URL of the repository and are followed by a path to the desired package. Therefore paths must be relative to the repository root. With a vanity import path you can make the path longer if desired, but not shorter (e.g. example.com/pkg
).
So the following is the shortest possible import path without a workaround: go.example.com/go/<module>
.
Workarounds
For the truly dedicated.
These involve a bit of setup and extra handling and might not be worth it just for the aesthetics of the import path.
There are two approaches I've worked out (and one semi-solution that probably won't work with a large number of modules). The first is setting up a module proxy. The second is creating another repo that copies from the go
directory and importing from there.
Use replace
in go.mod
This one is pretty simple, you can make the base import path anything you like and just replace
it in the go.mod
file.
Downside is this gets complicated to manage with many interdependent modules (as discussed in the linked article in the next section). Also feels less special and the burden is on the importing project to set up rather than the imported project.
Go Module Proxy
This article(gist) does a nice job explaining the approach.
go get
uses the GOPROXY
environment variable to decide where to look to find and resolve packages. The basic idea is to set up a proxy server that knows how to translate the public module name and get the relevant code from the actual repo, then put the URL of that server in the GOPROXY
variable.
Extra care is needed with this approach for private modules/repositories as you'll have to handle authentication as well.
Copy Git Repository
The final approach is to copy the contents of the go
directory to another repo, which can be automated with GitHub Actions or similar.
To preserve version tags (if used) and branches (although not commit hashes), you can use git filter-repo
to rewrite history so that the go
directory is actually the package root (and always has been): git filter-repo --subdirectory-filter go/
.
Then just set the vanity go-import
tag to:
<meta name="go-import" content="go.example.com git github.com/example/repo-go">
(where the original repo was github.com/example/repo
).