Snippet Wednesday - Executing Github Actions on a schedule

Executing Github Actions on a schedule

Introduction

Setting up CI/CD on your application/package repository is really helpful and as a developer you can have different usecases in which you would like to perform your tests.
Tests will be usually performed once you try to merge your MR / pull request into your main branch, but this may not be the only case when you’d like to perform a test.

For example, when you’re using external API’s, breaking changes may occur and this can cause your main branch (or tagged version) to break while you haven’t changed a thing…

In this snippet I’d like to show you how you can trigger an action on github, which will test your code and report your test coverage on set intervals of time.

Automating this can be helpful when you’re not actively working on a project, but still want to be notified when one of your tests fail. This may indicate you need to fix something.

Cron

Triggering a script or job can be done using cron, which is a time-based job scheduler for Unix operating systems. Part of setting up a cron job, is creating the right cron expression (schedule).
I will not go into detail, but a cron expression is a string made of 5 (or optionally 6) fields, separated by whitespace which represent a set of times.
The 5 field format used is as follows: minute hour day_of_month month day_of_week.
The allowed values per field are:

  • Minute: 0-59
  • Hour: 0-23
  • Day of month: 1-31
  • Month: 1-12 or JAN-DEC
  • Day of week: 0-6 or SUN-SAT
  • Year: 1970-2099 (optional 6th field)

You can use star expressions to indicate any value (*), a / will indicate a step value and - indicates a range of values and finally a , is a list separator.
In my usecase, I would like to schedule my tests to be performed every 6th hour on all days of the week, meaning they will run at 06:00, 12:00, 18:00 and 24:00.

The expression I will use is thus: 0 */6 * * *. A helpful website to check your cron expression is crontab guru.
Now we have made our schedule, it’s time to setup a Github Actions workflow on this schedule.

Running a Github Actions workflow on a cron schedule

On your Github repository, navigate to Actions and create a new workflow. You can also add a folder in your repository called: .github/workflows and the .yml definition in that folder.
At the start of this file we define the name of the workflow, together with the schedule:

name: Scheduled tests

on:
  schedule:
    - cron:  '0 */6 * * *' # Runs every 6th hour 

This is essential, everything we define from now on, is what will be executed at these times. Let’s start with setting up Python and install our dependencies.
Note that I am using a requirements.txt file and I’m installing pytest, pytest-cov and coverage separately.

name: Scheduled tests

on:
  schedule:
    - cron:  '0 */6 * * *' # Runs every 6th hour 
      
jobs:
  build:
    name: Scheduled tests
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: 3.11
    - name: Install dependencies
      run: |
        pip install pytest pytest-cov coverage
        pip install -r requirements.txt

Now, we will run our tests and create a coverage file, which also handily reports how much of our code is being tested and reports this. Therefore we add the following:

    - name: Run tests
      run: python -m unittest discover -b --start-directory ./tests
    - name: Build coverage file
      run: |
        pytest --cov=bro --cov-config=.coveragerc --junitxml=report.xml --cov-report=html:html/test-coverage-results
        coverage report --skip-covered || true

The first command of the previous block pytest --cov=bro --cov-config=.coveragerc --junitxml=report.xml --cov-report=html:html/test-coverage-results creates a html report with the coverage report (a nice extra). We can make this available as an artifact in the repository, therefore we add the following:

    - name: Archive code coverage results
      uses: actions/upload-artifact@v3
      with:
        name: coverage-results
        path: html/test-coverage-results
      if: ${{ always() }}
    - name: Download coverage results
      uses: actions/download-artifact@v3
      with:
        name: coverage-results

Now, add the full workflow file to your main branch in the repository and your tests + coverage report will be executed and built automatically on your defined schedule.

3 Likes