This tutorial explains how to set up a basic continuous integration workflow on GitHub Actions using Nix for package building. By building your package with Nix and uploading it to a binary cache, you'll make it easily accessible to users via the nix run
command. This process streamlines package distribution and installation.
The workflow builds the default Nix package defined in your flake using the following third-party actions:
- nix-quick-install-action to install Nix.
- cache-nix-action to save the Nix store to the GitHub Actions cache to reduce time spent on downloading dependencies.
- Optionally, you can enable cachix-action, so you can download the artifacts built on CI to your machines as Nix binary cache.
Note that there are some alternative hosted services for Nix CI. If the provided setup doesn't satisfy your requirements, you might consider the following options:
Adding files from the template
Section titled “Adding files from the template”Initialize the template from the root directory of the project:
Terminal window nix flake init github:akirak/flake-templates#metaAdjust the
.github/workflows/nix-build.yml
file to match your project requirements.Optionally, you can enable uploading to Cachix. Edit
.github/actions/setup/action.yml
and uncomment relevant sections:inputs:cachix-name:description: Name of the Cachix accountrequired: falsedefault: akirakcachix-token:description: Auth token for cachixrequired: true- uses: cachix/cachix-action@v16with:name: ${{ inputs.cachix-name }}authToken: '${{ inputs.cachix-token }}'Get an authentication token on Cachix and save it as a secret variable
CACHIX_AUTH_TOKEN
in your project.In each workflow in
.github/workflows
directory, pass the auth token to the action:- name: Set up Nixuses: ./.github/actions/setupwith:cachix-token: ${{ secrets.CACHIX_AUTH_TOKEN }}To save more assets to the cache (e.g. packages of a language-native package system), edit
.github/actions/setup/action.yml
and add their file paths topaths
option and tweakprimary-key
as needed:- name: Restore the package cacheuses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6with:primary-key: nix-${{ runner.os }}-${{ hashFiles('**/flake.lock') }}restore-prefixes-first-match: nix-${{ runner.os }}-gc-max-store-size-linux: 1Gpaths: |node_modules/.pnpmTo add more Nix-based workflows, just use the
./.github/actions/setup
action:jobs:some-nix-job:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Set up Nixuses: ./.github/actions/setup# with:# cachix-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
Building multiple packages and performing extra checks
Section titled “Building multiple packages and performing extra checks”By default, the CI workflow nix-build.yml
only builds the default package of the flake:
nix build -L
If your flake exposes multiple packages, you can use the following command instead to build all packages for each platform:
nix build ".#packages.$(nix eval --expr builtins.currentSystem --impure --raw).*" -L --option keep-going true
An alternative way is to add the packages to checks
and run nix flake check
:
nix flake check -L --option keep-going true
keep-going
option inverses the default behavior of fail-fast, which is convenient for CI.
Also see the following issue for updates: nix build --all: build all packages in a flake · Issue #7165 · NixOS/nix · GitHub
Running tests
Section titled “Running tests”To run tests using a contained environment in Nix, use checkPhase
and set doCheck = true
. Consult the builder documentation to see if it has any built-in check.
If you'd rather avoid running tests within Nix's sandbox, create a separate workflow instead in addition to the build workflow.
Also consider
Section titled “Also consider”- Update the actions automatically by setting up Renovate. This is already included in the template, so you don't need extra steps for configuration.
- The template also ships with a workflow for checking formats using treefmt-nix. It should work out of the box if your flake supports it, but otherwise it will fail. Check out the documentation for details.
- Use nix-fast-build if you are trying to build a flake containing several outputs with shared dependencies.