Github Actions for CI/CD

Github Actions are integrated tools in GitHub for Continuous Integration (CI) and Continuous Delivery (CD), i.e. it allows to automatically build, test and deploy software projects. For more details refer to the official documentation.

Action runners

Runners are the entities on top of which github actions are executed; in practice, they are docker images that run on remote github servers.

Self-hosted runners

To avoid computation limitation of github servers, one could use self-hosted runners, i.e. using the proper hardware to run github actions.

Installation of self-hosted runners is described here, but generally go to the repository settings, then to the Actions tab, and click on Add runner and follow the instructions there reported.

In this context it is also recommended to install docker.

Actions setup

GitHub actions are defined in yaml files in the .github/workflows directory of the repository. Files can have arbitrary names.

In general a github action workflow is defined as follows:

name: <name of the workflow>

on: <event that triggers the workflow>

jobs:
  <job name>:
    runs-on: <runner>
    steps:
      <steps to execute>

The name of the workflow is the one that will be displayed in the GitHub website in the Actions tab. A workflow can be triggered in different ways, and after that it will execute a series of jobs, each one might consist of several steps.

Workflow triggers

A GitHub action workflow might be triggered by different conditions, for instance the push on a specific branch, the creation of a pull request or a tag, a scheduled event and even manual triggers.

For instance the following allows to trigger the workflow when commits are pushed either on the main or develop branches:

on:
  push:
    branches:
      - main
      - develop

Conditions can be combined together; in the following example the workflow can be triggered manually or by a scheduled event:

on:
  workflow_dispatch:         # manual trigger
  schedule:                  # scheduled event
    - cron: '0 0 * * *'      # scheduling details

Note

Based on the cron documentation, this task is executed each day ad midnight. Check the link for more details.

Jobs

Jobs are a list of operations that must be executed within the workflow call; error in the execution of one or more jobs will mark the action run as failed.

One can think of workflows as a set of jobs that might (or not) have dependencies from one of another.

jobs:
  <job name>:
    runs-on: <runner>
    steps:
      <steps to execute>

As mentioned, runners are actually docker images, so one can choose from the Docker Hub images library of create a custom Dockerfile. As example are available ubuntu-latest to run the code on the latest released Ubuntu OS, but specific version also could be called (ubuntu-22.04). Usually images for specific environment are already configured (e.g. to work in node, python…).

After the steps directive the sequence of commands that needs to be executed are reported, as example

steps:
  - name: Checkout the repository
    uses: actions/checkout@v4

  - name: Source the ros environment
    run: |
      source /opt/ros/humble/setup.sh
      source ~/ros_ws/install/setup,sh

Each dash - is a new command; the name directive, even if its not mandatory, is useful to understand at which point of the workflow the execution is in a more intuitive way.

The uses directive is used to call an action that is already available in the GitHub Actions library; source code and documentation for each action can be found directly in GitHub looking at <username>/<repository>. In this case the checkout action is used to clone the repository in the runner’s workspace (the v4 tag is used to specify the version of the action to use).

The run directive is used instead to execute shell commands directly in the runner’s workspace.

Examples

Building documentation with Sphinx

This is the actual workflows configuration that is used to generate the documentation for this project. In particular it uses the Sphinx python library to generate the html page that is automatically deployed to the gh-pages branch of this repository in order to be served by GitHub Pages.

sphinx-build.yml
 1name: Sphinx Pages Builder
 2# The static web page should be built only on push on the main branch
 3on:
 4  push:
 5    branches:
 6      - main
 7
 8jobs:
 9  sphinx-build:
10
11    # Use a Ubuntu 22.04 runner
12    runs-on: ubuntu-22.04
13
14    # Required to write GitHub pages
15    permissions:
16      contents: write
17
18    steps:
19      - name: Checkout code
20        uses: actions/checkout@v4
21
22      # git is not provided by the ubuntu image by defauls
23      - name: Install git
24        run: |
25          sudo apt-get update
26          sudo apt-get install -y git graphviz
27
28      # set-up python 3.10 using the action script
29      - name: Set up Python
30        uses: actions/setup-python@v4
31        with:
32          python-version: '3.10'
33
34      - name: Install python depencencies
35        run: pip3 install sphinx furo sphinx-copybutton myst-parser
36
37      - name: Build docs
38        run: |
39          TZ=UTC sphinx-build . html
40
41      # Use a custom script to deply the html folder for pages
42      # https://github.com/peaceiris/actions-gh-pages
43      - name: Deploy pages
44        uses: peaceiris/actions-gh-pages@v3
45        with:
46          github_token: ${{ secrets.GITHUB_TOKEN }}
47          publish_dir: ./html