Skip to content

Building Go modules

With the default configs, you can already build a Go module without issues.

But, if you want to access module information in runtime (e.g. debug.BuildInfo or go version -m $binary), you'll need to setup GoReleaser to "proxy" that module before building it.

To do that, you can simply add this to your config:

# goreleaser.yaml
gomod:
  proxy: true

In practice, what this does is:

  • for each of your builds, create a dist/proxy/{{ build.id }};
  • creates a go.mod that requires your main module at the current tag;
  • creates a main.go that imports your main package;
  • copy the project's go.sum to that folder.

In which:

  • build.id: the id property in your build definition;
  • main module: is the output of go list -m;
  • main package: is the main module + your build's main;
  • current tag: is the tag that is being built.

So, let's say:

  • main module: github.com/goreleaser/nfpm/v2;
  • build's main: ./cmd/nfpm/;
  • current tag: v2.5.0.

GoReleaser will create a main.go like:

// +build: main
package main

import _ "github.com/goreleaser/nfpm/v2/cmd/nfpm"

a go.mod like:

module nfpm

require github.com/goreleaser/nfpm/v2 v2.5.0

Then, it'll run:

go mod tidy

And, to build, it will use something like:

go build -o nfpm github.com/goreleaser/nfpm/v2/cmd/nfpm

This will resolve the source code from the defined module proxy using proxy.golang.org. Your project's go.sum will be used to verify any modules that are downloaded, with sum.golang.org "filling in" any gaps.

Getting the version from the module

You can also get the module version at runtime using debug#ReadBuildInfo. It is useful to display the version of your program to the user, for example.

package main

import (
    "fmt"
    "runtime/debug"
)

func main() {
  if info, ok := debug.ReadBuildInfo(); ok && info.Main.Sum != "" {
    fmt.Println(info)
  }
}

You can also use go version -m my_program to display the go module information.

Limitations

  1. Extra files will still be copied from the current project's root folder and not from the proxy cache;
  2. You can't build packages that are not contained in the main module;
  3. VCS info will not be available.

More information

You can find more information about it on the issue that originated it and its subsequent pull request.

Make sure to also read the relevant documentation for more options.

Real example

Source code of a working example can be found at goreleaser/example-mod-proxy.