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...