DocOps at ATIX – the deploy stage: Automatically deploying to an internal http server via 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 „DocOps at ATIX“ blog article describes how we deploy our built documentation to an internal http server via our Documentation Gitlab Pipeline.

The first and second stage test and build the documentation.
To make our Gitlab pipeline even more convenient, we also deploy the build artifacts to an http server.
In our case, we extract the html, website, and style guide, and copy the pdf version to its designated location: a subdirectory named like its corresponding git branch.
This is a Gitlab feature and can be accessed as a predefined environment variable as ${CI_COMMIT_REF_SLUG}.

To do so, we have a third stage called deploy.
All jobs share common tasks as are descibed in the .deploy stage.

The deployment task uses an Alpine based Docker image.
Before running the actual script, we prepare SSH access by copying the SSH_KNOWN_HOSTS file into ~/.ssh/known_hosts and add a prepared SSH private key.

---
.test_deploy:
  extends: .deploy
  variables:
    SSH_KNOWN_HOSTS: "${DEV_SSH_KNOWN_HOSTS}"
    SSH_PRIVATE_KEY: "${DEV_SSH_PRIVATE_KEY}"
    TARGET_HOST: "dev-docs.example.com"

deploy:test_deployment:
  extends: .test_deploy
  dependencies:
    - build:website
    - build:html
    - build:pdf
    - build:style_guide
  environment:
    name: dev ${CI_COMMIT_REF_NAME}
    url: "http://dev-docs.example.com/branches/${CI_COMMIT_REF_SLUG}"
    on_stop: deploy:stop_test_deployment
  script:
    - set -u
    - ansible-playbook ci_resources/test_deployment.yaml
        --inventory "${TARGET_HOST},"
        --extra-vars "branch_slug=${CI_COMMIT_REF_SLUG}"
...

The following task describes how to deploy the website to our actual web server running docs.orcharhino.com.
This task only runs when started manually in our Gitlab pipeline, as we mostly push documentation online in sync with new orcharhino releases.
The only exception is bug fixes.

 ---
deploy:docs.orcharhino.com:
extends: .deploy
dependencies:
- build:website
environment:
name: production
url: https://docs.orcharhino.com/
variables:
SSH_KNOWN_HOSTS: "${PROD_SSH_KNOWN_HOSTS}"
SSH_PRIVATE_KEY: "${PROD_SSH_PRIVATE_KEY}"
TARGET_HOST: "${PROD_HOST_IP}"
script:
- set -u
- ansible-playbook ci_resources/prod_deployment.yaml -i "${TARGET_HOST}",
only:
refs:
- docs_orcharhino_com
when: manual
...

The variables "${}" refer to various Gitlab internal variables that are simply renamed.
This job only runs when started manually.
It starts an Ansible Playbook to deploy the documentation to our production server for docs.orcharhino.com.

---
.test_deploy:
extends: .deploy
variables:
SSH_KNOWN_HOSTS: "${DEV_SSH_KNOWN_HOSTS}"
SSH_PRIVATE_KEY: "${DEV_SSH_PRIVATE_KEY}"
TARGET_HOST: "dev-docs.example.com"

deploy:test_deployment:
extends: .test_deploy
dependencies:
- build:website
- build:html
- build:pdf
- build:style_guide
environment:
name: dev ${CI_COMMIT_REF_NAME}
url: "http://dev-docs.example.com/branches/${CI_COMMIT_REF_SLUG}"
on_stop: deploy:stop_test_deployment
script:
- set -u
- ansible-playbook ci_resources/test_deployment.yaml
--inventory "${TARGET_HOST},"
--extra-vars "branch_slug=${CI_COMMIT_REF_SLUG}"
...

The test_deployment job extends the test_deploy job which holds internal variables defined in Gitlab.
It depends on all four build stage jobs, as it only makes sense to deploy the documentation once it’s been built successfully.
It also starts an Ansible playbook but with a different inventory containing the internal http server and an extra variable called branch_slug to create a folder with the name of the feature branch ${CI_COMMIT_REF_SLUG}.

Overall, this mini-series with three parts allows you to rebuild our Gitlab pipeline to automatically test, build, and deploy Sphinx-based documentation.
It helps us focus on writing documentation rather than testing, building, and deploying it.
Using this Gitlab pipeline makes asking for reviews much more convenient and overall saves us a lot of time.

This post is also available in: Englisch