Lesson 05: GitHub Actions

Every time code is pushed to a repository, the same questions arise: do the tests still pass, does the linter raise any warnings, does the documentation build? GitHub Actions answers those questions automatically, without anyone having to remember to check. This lesson explains what Actions is, how workflow files work, and how Nestling uses it.


What GitHub Actions is

GitHub Actions is a continuous integration (CI) system built into GitHub. You define workflows in YAML files stored in .github/workflows/. GitHub runs those workflows on its own servers whenever specified events occur, typically a push to a branch or the opening of a pull request.

The result of each workflow run is shown on the pull request page as a green checkmark or red cross. A failing check blocks the PR from being merged (if branch protection rules are enabled), so problems are caught before they reach main.


Anatomy of a workflow file

A workflow file has three main parts: a name, triggers, and jobs.

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Install dependencies
        run: pip install -e ".[dev]"
      - name: Run tests
        run: pytest tests/
Part What it does
name Label shown on the GitHub Actions tab
on Events that trigger the workflow
jobs Independent units of work, each running on a fresh machine
runs-on The operating system for the runner (ubuntu-latest is the most common)
steps Ordered list of actions or shell commands within a job
uses Runs a reusable action from the GitHub Actions marketplace
run Runs a shell command directly

How Nestling uses Actions

Nestling has two workflow files:

.github/workflows/ci.yml: runs on every push to main and on every pull request targeting main. It runs three jobs in parallel:

Job What it checks
quality Linting with ruff and markdownlint via pre-commit
test Unit tests with pytest and notebook tests with nbmake
docs Documentation build with mkdocs build --strict

.github/workflows/deploy-mkdocs.yml: runs only on pushes to main. It deploys the documentation site to GitHub Pages using mkdocs gh-deploy.

The CI job must pass before any pull request can be merged. The deploy job runs after merge to keep the live documentation site up to date.


Status checks and branch protection

On GitHub, go to Settings → Branches and create a branch protection rule for main.

Useful settings for a research project:

  • Require a pull request before merging: prevents direct pushes to main.
  • Require status checks to pass before merging: blocks merge if any CI job fails.
  • Require branches to be up to date before merging: ensures the PR is tested against the current main.

With these rules in place, nothing reaches main unless the tests pass and at least one person has reviewed it.


Reading workflow output

When a workflow run fails, navigate to the Actions tab on GitHub and click the failing run. Each job is listed. Click into the failing job to see the step-by-step output.

Common failures and what they mean:

Error Likely cause
pytest: N failed A test assertion is wrong or a function changed its behaviour
ruff: E501 A line exceeds the maximum character length
markdownlint A markdown file violates a formatting rule
mkdocs build --strict A broken link or missing file in the documentation

Fix the issue locally, commit, and push. The workflow re-runs automatically.


Writing your own workflow

To add CI to a new repository, create the workflow directory and file:

mkdir -p .github/workflows

Create a minimal workflow at .github/workflows/ci.yml that installs your dependencies and runs your tests. Start simple. A single job that runs pytest is enough to begin with. Add linting and documentation checks once the basic test job is working.

Test locally before pushing

Run your tests locally before pushing to avoid cycles of push-fix-push. The act tool can run GitHub Actions workflows locally, which is useful for debugging complex workflows before they reach GitHub.

Actions minutes

GitHub provides a generous free tier of Actions minutes for public repositories (unlimited) and private repositories (a monthly allowance). For typical research code with fast test suites, the free tier is more than sufficient.


Further reading

The GitHub Actions documentation covers everything beyond what this lesson introduces: workflow syntax in full, the available runner environments, secrets management, reusable workflows, and the Actions marketplace. When your CI needs grow beyond a basic test-and-lint setup, the official docs are the right place to start.

This is the last lesson in the Git & GitHub track. If you have worked through all five lessons, you now have a complete Git workflow, from making your first commit to automated CI running on every push. That is a genuinely substantial set of skills, and the habits you have built here (clear commits, code review, automated checks) will serve you throughout your research.

For the next step in building good research software practices, see the Coding Practices track.