Automated Testing for Zig projects with Circle CI
Using Circle CI to provide Continuous Integration for projects written in Zig.
Automated testing is a handy tool for practicing Continuous Integration. There are a lot of different services and platforms available to developers to help automate testing for your projects. In this post, I'll be exploring using CircleCI to automatically test a Zig based project.
Throughout this post, I will be using two simple projects, both of which are available in a companion repository that also includes the configuration for the CI service. The first of these is the default project that Zig creates when running zig init-lib
. The other is a little more involved, making use of SDL to render a window on screen - whilst this project doesn't have any tests, we want to ensure that it builds.
I will be assuming that you already have your repository configured and connected to the CI service.
Circle CI
CircleCI provides a free plan that allows one job to be ran at a time. We'll take advantage of their Docker support to run our CI. I maintain a Docker image for Zig that publishes tags for both the latest releases - latest
- and the latest master releases (which are updated at midnight every night) - master
.
We will be testing against both the most recent release and the latest master release.
Testing the simple sample project
There are a couple of steps we need to take to test our simple project:
- Checkout the code that we want to test.
- Print the version of Zig that we're using, which is particularly useful in the case of master releases.
- Run
zig build test
to run our tests.
Circle CI uses YAML files to configure workflows. I've included the required configuration below to achieve the above steps:
version: 2.1
jobs:
test_latest:
docker:
- image: euantorano/zig:latest
working_directory: ~/repo
steps:
- checkout
- run:
name: print zig version
command: |
zig version
- run:
name: run tests
command: |
zig build test
test_master:
docker:
- image: euantorano/zig:master
working_directory: ~/repo
steps:
- checkout
- run:
name: print zig version
command: |
zig version
- run:
name: run tests
command: |
zig build test
workflows:
version: 2
commit:
jobs:
- test_latest
- test_master
The above configuration defines two jobs - one to test against the latest Zig release (test_latest
) and another to test against the latest Zig master release (test_master
). We then use these jobs within a workflow that we call commit
that doesn't have any set trigger as the default is to trigger the workflow when pushing to a branch.
Each of these jobs defines a couple of steps to checkout the code, run a command to print the Zig version, then run the tests.
Building the SDL sample project
The SDL project is a little bit more involved - we need to make sure that the SDL development headers and the SDL library itself are installed before we try building the project. The Zig Docker image doesn't ship with either of these installed, but we know that it's based on Alpine Linux so we need to install the following two packages:
The easiest way to do this is to create a custom Docker image based off of the standard Zig image that will install these packages. In this case, I'm only going to test against the latest Zig version, but you could test against the master image too with another Docker image. Create a Dockerfile like the following:
FROM euantorano/zig:latest
RUN apk add --no-cache sdl2 sdl2-dev
Now we just need to write our build configuration file. We'll be adding an extra step compared to the simple project, so our steps will be:
- Checkout the code that we want to test.
- Build the Docker image.
- Print the version of Zig that we're using, which is particularly useful in the case of master releases.
- Run
zig build
to build our project.
The configuration to perform these steps should look something like the following:
version: 2.1
jobs:
build_sdl_latest:
machine: true
working_directory: ~/repo
steps:
- checkout
- run:
name: build docker image
command: |
docker build -t zig-sdl2 .
- run:
name: print zig version
command: |
docker run zig-sdl2 version
- run:
name: build app
command: |
docker run -v $PWD:/app zig-sdl2 build
workflows:
version: 2
commit:
jobs:
- build_sdl_latest
The above configuration uses the machine executor, which has Docker installed and ready to use. It defines a single job build_sdl_latest
with several steps:
- Check out the code.
- Build a docker image using the
Dockerfile
in the root of the repository and tag it aszig-sdl2
. - Then use the created image to print the Zig version.
- Then finish up by using the Docker image to build the project.