FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects

DevOps Guidebook

This repository contains the source for the UIS DevOps Guidebook

Hosting

The guidebook is hosted via GitLab pages. readthedocs.org (RTD) and is automatically deployed on each commit to master. The GitLab pages-managed URL is at https://uis.uniofcam.dev/devops/docs/guidebook/.

To support a custom domain, the guidebook.devops.uis.cam.ac.uk DNS record is a CNAME pointing to uis.uniofcam.dev.io following the custom domain documentation.

Local Development

The guidebook uses mkdocs to convert Markdown source into a static website. You can run it from either the dockerised setup or your own local environment.

To begin development, install pre-commit and clone the repo locally:

git clone git@gitlab.developers.cam.ac.uk:uis/devops/docs/guidebook.git
pre-commit install

Start the guidebook via:

docker-compose up --build

The local documentation is now available at http://localhost:8000/.

Adding a page

  1. Create a Markdown file in the relevant directory under docs.
  2. Add this file's path to the nav configuration in mkdocs.yml.

Service Information

Service & team information is encoded in services.yml.

When adding or updating a Service page, you must update that file to define such information.

Comments in the file itself describe each section's format.

The file is exposed at endpoint /api/services.yml for consumption by other apps/services, via a script in the Gitlab CI config.

NOTE:

  • The canonical source of DevOps teams and team-service mappings is this Google Doc.

  • This YAML configuration simply encodes the information in a machine-parsable format, and must be manually updated to remain in-sync with that document.

Site-Relative URLs

Site-relative URLs can be specified using site:path/to/some-page.

This functionality is provided by a custom hook in hooks/site_urls.py

These are preferable to relative URLs, since:

  • A page containing site: URLs needn't change if it's relocated.
    • Whereas, a page containing relative URLs would need all of them updated.
  • A page referenced by site: URLs can be relocated, then a single search-and-replace performed to update all references.
    • Whereas, a page referenced by different relative URLs requires that they all be updated, and each becomes defferent.

Such site: urls are translated as follows, depending on whether the code is running locally or in Gitlab CI, where flag --no-directory-urls is passed to mkdocs build:

Example site: URL Doc Path Local URL CI Artifact URL
with --no-directory-urls
site:path/to/page docs/path/to/page.md /path/to/page/ $SITE_ROOT/path/to/page.html
site:path/to/page/ docs/path/to/page.md /path/to/page/ $SITE_ROOT/path/to/page/index.html

Custom Plugin Syntax

Some MkDocs extensions & plugins used (see mkdocs.base.yml) provide custom syntax to utilise their new visual elements.

Here's a summary of the custom syntax we utilise, provided by our configured extensions & plugins:

Extension / Plugin Notation Meaning
Admonitions !!! note, ??? tip, etc. A styled callout, which may be collapsible
PymdownX > Snippets --8<-- "path/to/file.(md|ext)" Insert contents of the specified file.
Neoteroi > Cards [cards cols=2 smaller(path/to/cards.(json|yml))] Insert the visual cards defined in specified file.
Site-Relative URLs (see section below) site:path/to/some-page Site-relative URL (in our case docs/path/to/some-page.md)

Macros

The guidebook uses a set of macros to provide a consistent look and feel to the documentation.

Also to auto-generate certain information based on static configuration (.yml) files.

The MkDocs-Macros plugin is used to simplify this process.

  • It loads main.py to access & apply all custom macros.
  • Those are stored within macros/.
  • To add a new macro, either add to or create a file in macros/.py.

Create a New Template Variable

If you want to add a new template variable, simply define it in TEMPLATE_VARIABLES within macros/constants.py.

It will then be available within all .md files as {{ my_variable }}.

Create a Macro Mixin

If adding macros for a new context, create a new file macros/{my-context}.py:

from ..render import hyperlink # etc

def define_env(env):
  env.macro(my_macro)
  # ..wrap all other macros too..

def my_macro(...):
  pass # return render result here e.g. hyperlink(...)

Then import and invoke your module's define_env in macros/__init__.py:

from . import (..., my_context, ...)

def define_env(env):
    # ...
    my_context.define_env(env)
    # ...

In similar fashion, add to macros/render any needed context-specific HTML rendering (see existing examples there).

Your macro(s) will then be available within all .md files as {{ my_macro(..args..) }}.