Fighting with Github Actions

Fighting with Github Actions

Github Actions is a great product for continuous integration built directly into Github. I primarily use it to run unit tests automatically. However, getting it setup properly has been a challenge. This is an evolving set of notes on how to get it to work consistently.

Github actions are specified in a YAML file in any repository under the path .github/workflows.

Choosing When To Run an Action

The first part of an action specifies when it runs. This is usually through the adverb on. The following code is used to do a common pattern that is surprisingly difficult: Run the action on push or pull request but not both.

on:
  push:
  pull_request:
    branches:
      # Branches from forks have the form 'user:branch-name' so we only run
      # this job on pull_request events for branches that look like fork
      # branches. Without this we would end up running this job twice for non
      # forked PRs, once for the push and then once for opening the PR.
    - '**:**'

Specifying Jobs

Jobs are the meat of the action. Often, you, need to checkout the repository, install any dependencies and run tests. Optionally, you can do a deployment step, but I haven't done much of that yet.

Below is an example that installs python and poetry, a dependency management system for python. I also cache the folder ~/.cache/pypoetry/virtualenvs, which is the location poetry stores any dependencies. The cache is refreshed anytime poetry's lock file poetry.lock changes. Once the dependencies are installed, I use pytest to run the unit tests.

jobs:
  #Run pytest
  test:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2

    - name: Install python
      uses: actions/setup-python@v2
      with:
        python-version: '3.7'

    - name: Install poetry
      uses: Gr1N/setup-poetry@v4

    - name: Cache poetry dependencies
      uses: actions/cache@v2
      with:
        path: ~/.cache/pypoetry/virtualenvs
        key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }}
        restore-keys: |
          ${{ runner.os }}-poetry-
    
    - name: Install dependencies
      run: poetry install -E experiments

    - name: Run pytest
      run: poetry run pytest --doctest-modules

For a full example in context, see here