Automated test on NixOS repository with Gitlab CI/CD
The NUR repository template integrates automated tests done by Travis CI to check code integrity with every GIT commit. Only if the automated build process succeeds, commited package changes are applied to the main NUR repository.
For me this was the first introduction to CI/CD (continuous integration / development). In case of the NixOS user repository (NUR), using this strategy to test changes and their code integrity does make sense to avoid breakage. Since I always try to host code on my own Gitlab instance, I was curious how to implement this on Gitlab. The NUR repository doesn’t provide any references for such use cases.
Setup Gitlab runner
The following guide assumes that you’ll have Gitlab and Docker already installed, configured and running. I’ve tested the setup on my ArchLinux server but it should also work on other systems.
The runner is the backend application which will handle the tests and jobs defined in gitlab-ci.yml. You can install it on the same machine Gitlab is running or on a different host. Install and configure the runner with following commands
pacman -S gitlab-runner
gitlab-runner register
Unfortunately we have to use the gitlab-runner
command to configure it. It is not possible to just create a configuration file yet.
We’ll have to provide some common settings to the register command:
- URL: https://git.project-insanity.org (url of your Gitlab instance)
- Token: You can get this token from the runner administration page at “/admin/runners”
- Name / description:
Docker runner
- Tags: You can skip this. For simplicity we’ll use this runner for all pipelines without any tags
- Executor:
docker
- Docker image:
nixos/nix
To keep it simple, the newly created runner should run on all pipelines of all repositories (regardless of the tags specified). Go to the administration panel, select Runners
and click the edit symbol for the Docker runner
. Enable the option “Run untagged jobs”, meaning “Indicates whether this runner can pick jobs without tags“. Click on Save changes
.
Configure the pipeline
A pipeline is a repository specific definition of jobs which should be triggered by a new commit. The pipeline is configured by a file called gitlab-ci.yml
which should be included into the root directory of your Git repository / project.
This is the file I’m using for my NUR repository. It is based on a comment by Jake Waksbaum in the Gitlab.com bugtracker.
image: nixos/nix
variables:
# The repo name as used in
# https://github.com/nix-community/NUR/blob/master/repos.json
NUR_REPO: "onny"
NIXOS_VERSION: "20.03"
NIXPKGS_ALLOW_UNFREE: "1"
NIXPKGS_ALLOW_INSECURE: "1"
stages:
- build
- deploy
before_script:
- nix-channel --add https://nixos.org/channels/nixos-${NIXOS_VERSION} nixos
- nix-channel --update
- nix-env -iA nixos.curl
build:
stage: build
script:
- nix-build
#- cp result/* . FIXME
- rm -r result
#cache:
# paths: /nix/store
artifacts:
untracked: true
deploy:
stage: deploy
script:
- curl -XPOST "https://nur-update.herokuapp.com/update?repo=${NUR_REPO}"
when: on_success
In this example, the option image
defines which Docker container to use. Change the NUR_REPO
variable below according to your chosen username. Stages structure the pipeline process and contain jobs which will execute commands. Our build
stage will run the commands to build the NUR repository, e.g. building all packages. If this succeeds, the deploy stage will be run and will register the latest commit on the main NUR project. Read the official documentation for further explanation on Gitlab CI commands.
Is gitlab-ci.yml
part of your project root folder, the runner on Gitlab will use this file to start the pipeline. The screenshot above shows the build log and return status of the pipeline on the project page.
Limitations
The build job, which will trigger the nix-build command, will fetch a lot of packages and compile all programs again, even if a specific package script haven’t been modified. There are several approaches discussed to achieve a persistent and shared Nix store cache between the different Docker runner sessions.
The user turion recommends using the online service Cachix, which will retain precompiled binaries for later pipelines. Other more complicated solutions are discussed in this Gitlab issue.
Nevertheless it would be cool to see official Gitlab CI/CD support in NUR quite soon :)
Update Oct 2020:
- This post got featured in NixOS Weekly Newsletter Oct 2020 (Archive 1, 2)
Nice guide. I’ve been doing something similar for my repos so I extracted the CI configuration into another repo that I can just import.
https://gitlab.com/kevincox/nix-ci/
It’s been slowly growing features. For example it builds attributes then can select which attributes to export as artifacts. It also has cachix support for avoiding rebuilds. I do need some more features still such as support for other binary caches (both read and write) but it’s good enough for my projects.
You can see a (complex) example user here: https://gitlab.com/kevincox/feed-test/-/blob/master/.gitlab-ci.yml (or just about any of my other projects)