Build and install software via CI, keep GC root


#1

Hi! We’re using Gitlab CI to build software via Nix (via nix-build, that is) and would like to have the resulting binary in result/bin/ accessible on the (same or maybe even a different) server.
As I understand it, after the CI is finished building, it will remove the whole work directory, along with the result symlink, which, in turn, tells Nix to collect the software when nix-collect-garbage is run.
So I guess what we want is to copy the binary somewhere globally accessible and tell Nix to not garbage collect it. Is this easily possible?
I’d like Nix to garbage collect old versions of the software, of course, and only keep the latest.

Note: we’re not using NixOS, just Nix!


#2

If you have a store somewhere, then you could nix copy the result into the store. Another option is to use nix dump-path to create an archive and load that again with nix add-to-store.


#3

@FRidh Thanks for your answer, but I don’t understand. I thought after I nix-build something, it’s already in the store?
Maybe I didn’t specify our setup enough: We have Gitlab CI set up so builds run as a special user that has Nix installed (so via a per-user installation). That is, the build server already has a store, and stuff from CI is put there (I think) via nix-build. I’m not sure if the build results in the store are visible (and executable) to other users, though.
On a more general note: Where is the documentation for all these nix commands? The Nix manual specifies these as equivalents of old nix-foo commands, and links the source code (!?) as a description?


#4

With store I meant a Nix store, elsewhere. You’ve asked for a way to store your package, and you can’t save it locally because it gets removed. Nix allows you to transparently copy paths from one store to another over ssh.

The nix executable is not explicitly documented in the manual, aside from being mentioned in the changelog. Instead, nix --help will show all commands.


#5

Do I understand correctly that your CI only removes the working directory, but leaves other changes intact? That would allow you to create a gc-root outside your working directory, or even just use nix-env to --set a profile.


#6

@tilpner You’re correct, the CI has a working directory that it creates before building and removes after building. The source is copied there and nix-build is invoked.
How would I add a gc-root?


#7

If you have a place to store these symlinks, you can specify --out-link path to tell nix-build where to create the result symlink. You could also try nix-store with --add-root (and maybe --indirect). Finally, nix-env --profile /nix/var/nix/profiles/ci/id_of_jobset --set $RESULT might be worth considering.


#8

Ah, I think --out-link is exactly what I need. I’m not sure what nix-env --profile is doing (seems to understand that I have to read a lot of documentation :D)


#9

I am not sure about the atomicity of any of these, which might not even be a problem for you if you don’t replace any symlinks. Without checking the source, I’d expect nix-env to have gotten it as-right-as-possible (and would consider it worth fixing if it hasn’t).

Be careful to not move links around, that will break gcroots, and is only allowed in directories reachable via /nix/var/nix/gcroots (AFAIK).