DocOps at ATIX – the test stage: Adding ‘make linkcheck’ to our Documentation Gitlab Pipeline

This short blog series will explain how we automatically test, build, and deploy documentation mostly using vim, git, sphinx, docker, and gitlab. This blog article describes how to use ‚make linkcheck‘ and add it to our internal Gitlab pipeline.

Currently, our test stage only contains one job: run make spellcheck.
Now, we want to extend our test stage with the linkcheck make target.
All make targets can be viewed by simply running make in the Git directory which houses the Makefile.

Running it locally saves the output to _build/linkcheck/output.txt and exits with either 0 or 1 as you’d expect.

Our current pipeline as described in .Gitlab-ci.yml looks as follows:

---
stages:
- test
- build
- deploy

variables:
REGISTRY: registry.example.com
ACCEPTED_WARNING: 'WARNING: toctree contains reference to excluded document ''sources\/privacy_policy'''

.build_image:
tags:
- docker
- dev_infra
image: ${REGISTRY}/debian/buster_slim/sphinx_doc_builder:master
before_script:
- pip3 install -r requirements.txt

.test:
extends: .build_image
stage: test
allow_failure: true

test:spelling:
extends: .test
variables:
OUTPUT_FILE: "${CI_BUILDS_DIR}/${CI_PROJECT_PATH}/_build/spelling/output.txt"
script:
- make spelling
- cat "${OUTPUT_FILE}"
- '[[ $(wc -l < "${OUTPUT_FILE}") -le 0 ]]'
...

The rest of the file will be displayed in the following articles.

Our pipeline is separated into three stages as outlined in the first article.
Two variables are set: the URL to our container registry and an accepted warning which we already expect and are fine with.
For every job, we basically start a Docker container and install Sphinx including its requirements which are stored in Git as requirements.txt.
The test stage extends the build_image part and is allowed to fail, i.e. other stages will run even if there are spelling errors.

The Docker image is built in another Gitlab pipeline and stored in our internal Gitlab Container Registry.
This means that not all required packages have to be installed with each run, only the ones defined in requirements.txt.

Now, let's add a second job to the test stage.
---
test:linkcheck:
extends: .test
variables:
OUTPUT_FILE: "${CI_BUILDS_DIR}/${CI_PROJECT_PATH}/_build/linkcheck/output.txt"
script:
- make linkcheck 2> >(tee errors.txt)
- cat errors.txt
- sed -i "/${ACCEPTED_WARNING}/d" errors.txt
- '[[ $(wc -l < "errors.txt") -le 0 ]]' ---

This job simply appends the yaml code shown before.
The linkcheck job also extends the .test part.
A variable is defined to save its output to _build/linkcheck/output.txt.
The script is comparable to the spelling job: it runs the make target linkcheck and splits the standard output and error to console and a file.
The file is then printed to stdout to view it directly in the Gitlab console for said job.
Then, we remove an accepted warning (this comes from building two different HTML versions for the website and .rpm package with one excluding a file that's included in the table of contents) in the file.
Last, we count the lines of said file.
If it's zero, exit with 0 (as in everything's fine), if not, exit with 1 as in there's been an error.

Due to the allow_failure: true, the next stage will run irrespective of the results of the test stage.

The next article will cover our build stage.