Using nix to build my personal website

Modifying the existing GitHub Action workflow for building the website to use cachix/install-nix-action and nix-shell

This is a follow-up to my previous article about setting up a simple Ruby development environment using nix-shell in which I mentioned I wasn't certain I'd completely specified the development environment. Although it's a bit of a tangent from my main aim of configuring isolated development environments, I thought it would be instructive to modify the GitHub Action workflow that automatically publishes this website to use nix.

Modifying the GitHub action workflow to use nix

I found cachix/install-nix-action and decided to use it in my workflow along with the shell.nix & gemset.nix files I'd already created. I had to remove the specification of a "ruby:2.6.6" container image, because this did not include a number of packages required by the install-nix-action step to install nix. Removing this specification meant that the workflow fell back to using GitHub's "ubuntu-latest" virtual environment which comes with loads of OS packages installed including those needed to install nix.

I then inserted the install-nix-action step immediately after the existing actions/checkout step, removed the steps installing node.js and the bundled gems, and modified the step which built the website to run nix-shell --command 'middleman build', i.e. to build the site within the shell specified by shell.nix.

At this point slightly to my amazement, the build ran successfully!

name: Continuous Deployment to GitHub Pages
on:
  push:
    branches:
      - main
jobs:
  build:
    name: Build
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repo
        uses: actions/checkout@master
      - uses: cachix/install-nix-action@v10
        with:
          nix_path: nixpkgs=channel:nixos-unstable
      - name: Build site
        run: nix-shell --command 'middleman build'
      - name: Publish site
        uses: maxheld83/ghpages@v0.2.1
        env:
          GH_PAT: ${{ secrets.GH_PAT }}
          BUILD_DIR: ./build

You can see all the changes I made in this commit.

Observations

As with the experience of running nix-shell on my local machine, I belatedly realised node.js was being made available by the GitHub virtual environment and not by nix-shell. I did spend a bit of time investigating this by basing the workflow on a minimal container image, but it turns out that it's not trivial to prepare a container image suitable for installing nix. So I decided to give up at this point. Although it meant I still hadn't definitively proved I'd completely specified the development environment, I'd convinced myself that I understood what was going on and could prove it given enough time!

I was pleasantly surprised to see that the nix-based build were significantly quicker than the original build, even though the bundled gems were being cached in the latter. Some of the speed-up can be attributed to the fact that the nix-based build doesn't have to spin up a separate container, but from a cursory look at the logs most of the gain seems to be in not having to install the bundled gems.

Next steps

While this was an interesting diversion, I plan to get back on track by creating a development environment for a simple Rails app, probably this one which doesn't need a database.