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.

Job of pipeline is failing in Gitlab CI

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: