blob: 3336482ccd7dc5901f360c1d5cb75e3f768c4305 (
plain) (
tree)
|
|
---
title: DIY bare bones CI server with Bash and Nix
date: 2020-11-12 3
layout: post
lang: en
ref: diy-bare-bones-ci-server-with-bash-and-nix
eu_categories: ci
---
With a server with Nix installed (no need for NixOS), you can leverage its build
isolation for running CI jobs by adding a [post-receive][post-receive] Git hook
to the server.
In most of my project I like to keep a `test` attribute which runs the test with
`nix-build -A test`. This way, a post-receive hook could look like:
```shell
#!/usr/bin/env bash
set -Eeuo pipefail
set -x
LOGS_DIR="/data/static/ci-logs/libedn"
mkdir -p "$LOGS_DIR"
LOGFILE="${LOGS_DIR}/$(date -Is)-$(git rev-parse master).log"
exec &> >(tee -a "${LOGFILE}")
unset GIT_DIR
CLONE="$(mktemp -d)"
git clone . "$CLONE"
pushd "$CLONE"
finish() {
printf "\n\n>>> exit status was %s\n" "$?"
}
trap finish EXIT
nix-build -A test
```
We initially (lines #5 to #8) create a log file, named after *when* the run is
running and for *which* commit it is running for. The `exec` and `tee` combo
allows the output of the script to go both to `stdout` *and* the log file. This
makes the logs output show up when you do a `git push`.
Lines #10 to #13 create a fresh clone of the repository and line #20 runs the
test command.
After using a similar post-receive hook for a while, I now even generate a
simple HTML file to make the logs available ([example project][ci-logs])
through the browser.
[post-receive]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
[ci-logs]: https://euandreh.xyz/remembering/ci.html
## Upsides
No vendor lock-in, as all you need is a server with Nix installed.
And if you pin the Nixpkgs version you're using, this very simple setup yields
extremely sandboxed runs on a very hermetic environment.
## Downsides
Besides the many missing shiny features of this very simplistic CI, `nix-build`
can be very resource intensive. Specifically, it consumes too much memory. So if
it has to download too many things, or the build closure gets too big, the
server might very well run out of memory.
|