1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
+++
title = "gomodsri"
summary = "Using taislcale/nardump to generate a go module SRI without building first"
date = 2024-03-10
category = "Nix"
+++
### The problem
When building a Go module with `nix`, generally one uses `buildGoModule`. One thing this shares with other builders in the nix ecosystem is `vendorHash` (or similar name).
Although there _have_ been various workarounds, there's usually no getting around some variation of building, noting the "expected" new hash, and replacing the hash with the correct one before building works for real.
### The solution
Now, admittedly I am borrowing this idea from [tailscale](https://tailscale.com). I simply wrapped it in a (nu)shell command for easier usage more generically.
The original idea combines the command [nardump](https://github.com/tailscale/tailscale/tree/ad33e47270509345469af795aed65177df88904e/cmd/nardump) with the [vendoring](https://pkg.go.dev/cmd/go#hdr-Make_vendored_copy_of_dependencies) ability of Go modules to predict the `vendorHash`. Put together, it can look something like the following:
- [update-flake.sh](https://github.com/tailscale/tailscale/blob/ad33e47270509345469af795aed65177df88904e/update-flake.sh#L9-L10)
```sh
# [...] setting up a tempdir
go mod vendor -o "$OUT"
go run tailscale.com/cmd/nardump --sri "$OUT" >go.mod.sri
# [...] cleanup
```
- [flake.nix](https://github.com/tailscale/tailscale/blob/ad33e47270509345469af795aed65177df88904e/flake.nix#L69)
```nix
pkgs.buildGoModule {
# ...
vendorHash = pkgs.lib.fileContents ./go.mod.sri;
# ...
}
```
---
I've modified it locally to use across other projects as the following nushell function:
```nu
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'
}
```
<small>Yes, the echo at the end is because I always forget the invocation otherwise...</small>
|