jolheiser


gomodsri

Nix

Sun, 10 Mar 2024

The problem

When building a Go module with nix, generally you would use buildGoModule. Like other builders in the nix ecosystem, it uses a vendorHash property (or similar name).

Although there have been various workarounds, the process typically involves building, noting the "expected" new hash, and replacing the old hash with the correct one before the build succeeds.

The solution

My solution is inspired by tailscale, which I've adapted into a (nu)shell command for easier generic usage.

The original idea starts with the nardump command. This is combined with the vendoring ability of Go modules to predict the vendorHash. Put together, it can look something like the following:

# [...] setting up a tempdir
go mod vendor -o "$OUT"
go run tailscale.com/cmd/nardump --sri "$OUT" >go.mod.sri
# [...] cleanup
pkgs.buildGoModule {
  # ...
  vendorHash = pkgs.lib.fileContents ./go.mod.sri;
  # ...
}

I've modified it to use across other projects as the following nushell function:

def gomodsri [] {
  let tmp = (mktemp -d)
  go mod vendor -o $tmp
  let sri = (go run tailscale.com/cmd/nardump@latest --sri $tmp)
  $sri | save -f go.mod.sri
  rm -rf $tmp
  echo 'nixpkgs.lib.fileContents ./go.mod.sri'
}

The echo at the end is because I always forget the invocation otherwise...