For a long time I've been manually deploying this blog to GitHub Pages. This worked OK because I publish less than once a month. But I always wished for a better, automatic solution. Recently I used Nix to rebuild my home network and I was curious if I can improve the workflow of publishing my articles to thewagner.net.
The blog is served from GitHub Pages so I don't have to manage any servers. GitHub expects the HTML pages in a repository with a specific name: in my case this is wagdav.github.com. This repository only hosts generated content. I push to this repository when I want to publish the changes in the source repository.
I configured Travis CI to execute the build and deploy steps when a change is committed to the source repository.
- The source repository thewagner.net stores articles.
- The deployment repository wagdav.github.io stores generated HTML pages.
- When triggered, Travis CI checks out the source repository, builds the blog and pushes the generated files to the deployment repository.
Let's see the build and deploy steps in detail.
The build pipeline is defined as a Nix expression. I don't explain how it works, but I highlight the steps it performs:
- Build the static website using Pelican.
- Run static analysis on the bash scripts using shellcheck.
- Run markdownlint to flag formatting issues in the articles.
These steps depend on tools from three different language ecosystems: Pelican is a Python project, shellcheck and markdownlint are written in Haskell and Ruby, respectively. Yet, the only dependency of running this pipeline is the Nix package manager.
To execute all the checks and build the blog I run:
All dependencies are pinned to a specific version of Nix Packages therefore this command always uses the same version of every tool and library no matter where or when it is executed.
A shell script pushes the generated HTML files to the deployment repository:
Because the script runs within a Nix shell, again, Nix is the only dependency and I don't have to install any additional tools or libraries to run it.
The commands described in the previous sections can be executed on my local workstation. However, to deploy my changes reliably I choose Travis CI to automate the build, check and deployment steps.
The Nix support of Travis CI is fantastic: it takes only seven lines of sweet YAML to setup everything:
language: nix deploy: provider: script script: nix-shell scripts/publish.sh $GITHUB_TOKEN on: branch: master
Behind the scenes this configuration builds the artifacts described in
default.nix and executes the publish.sh when
the change was triggered on the
master branch. The secret value
GITHUB_TOKEN is configured on the Travis CI web interface.
Deploying my blog is now fully automatic: I only push the contents of the articles to a repository. A hosted service builds and deploys the HTML pages. I can develop, test and execute each step of the pipeline locally and the dependency on hosted services is isolated to a few lines of code.