Go builder with `replace ... -> ` statements in `go.mod` inside mono-repo

I have here a mono-repo where we enabled some Nix tooling, but I have some difficulties with vendorHash
and go.mod containing replacements replace bla/bla/bla -> ../../mymodule-a.

The monorepo consists of components, e.g. a and lib-common

- components
  +- /lib-common  <---------------------------------------+
  |    + go.mod   					  |
  |  							  |
  +- /a                                                   |
      + go.mod (has "replace company/lib-common -> ../lib-common")
      + default.nix

The component a reuses a lib-common which is also just a Go module.
I can build a with Nix and the buildGoModule function by setting the correct vendorHash and also doing some gimick with
lib.fileset library to include all relevant sources which a needs to build
→ it needs components/lib-common and it-self components/a.

The question is: For local development this works great with replace ... in go.mod, however
the problem is:

  • Whenever something changes in lib-common the user HAS to change the vendorHash in the default.nix, because if the user does not,
    the Nix build in default.nix MAY take an old chached derivation for the goModules (the dependencies)
    which includes lib-common and a might compile but does not have the current changes from lib-common which is bad

I am searching a way to kind of work around that problem.
Does anybody have anything in mind here which makes a nice tooling such that one does not need to
constantly think about these vendor hashes with the replace tooling in place or a better option?.

I found the following things, but not sure of all the caveats.

  1. Employ some automatism to remind the user of checking vendorHash (if its not current) and
    updating it, but how?? Our Nix CI might have chached things and might just build the derivation although its wrong…
    Maybe there is an option to delete all derivations with /nix/store/XXXXX-go-modules or find the one which a/default.nix depends on?

    • Change everything to vendorHash = null and go mod vendor all components.
      Pro: The update is easier as go mod vendor can be executed and not nix build → copy hash → replace in default.nix, but if 1. is not possible its still flawed…
  2. Adjust the builder (our custom one)
    such that it deletes all <modulePaths>s in replace <modulePath> -> <rel-path> from the fetched vendor folder in the postInstall step
    of the builder and in the preBuild step we place a symlink at vendor/<modulePath><rel-path>
    such that the build succeeds. (tested this and might work)

1 Like

sidenote:

There is actually a way to delete the goModules derivation on the buildGoModule function:

nix store delete $(nix show-derivation "./tools/nix#myapp.goModules" | jq -r ".[] | .outputs.out.path")

and

proxyVendor = true will use go mod download which will not download replace statements.