Skip to main content

Github Actions

MNE-CPP uses GitHub Actions for all continuous integration (CI) work. GitHub Actions operates on repository events — pushes, pull requests, releases, and timers — which trigger workflows defined as YAML files in .github/workflows/. Each workflow contains one or more jobs, and each job runs a series of steps on a fresh virtual machine (runner). You can read more about the terminology in the GitHub Actions documentation.

Workflow Overview

MNE-CPP's CI is organized around the Main – Staging – Feature branch model. The following table summarizes every CI workflow:

Event typeWorkflow NameWorkflow ScriptEffect
Pull Requests → staging or mainPullRequestpull-request.ymlBuild matrix (Qt min + max) and tests on all platforms. PR cannot be merged until all jobs pass.
Pushes to stagingStagingstaging.ymlDev release binaries, code coverage with threshold/regression checks, dev website + Doxygen deployment, CodeQL analysis.
Pushes to mainMainmain.ymlBuilds, tests, stable website + Doxygen deployment.
Tag v* on mainMain (release jobs)main.ymlFull stable release: platform binaries (Linux, macOS, Windows), installers, WebAssembly, Codecov upload.
Pushes to the wasm branchWasmTestwasmtest.ymlCreates new versions of the WebAssembly capable MNE-CPP applications and makes them accessible via the repository's gh-pages branch.
Timer runs outCoveritycoverity.ymlTriggers every two days to run Coverity static code analysis tools.
Pushes to the generateqt branchBuildQtBinariesbuildqtbinaries.ymlTriggers builds of all needed Qt versions and makes them accessible as artifacts via the Github Actions interface.

Reusable Workflows

Common build and test logic is extracted into reusable workflows to avoid duplication:

WorkflowScriptPurpose
Reusable Build_reusable-build.ymlCross-platform build parameterized by Qt version
Reusable Tests_reusable-tests.ymlTest execution with configurable code coverage (Codecov upload, threshold check, or plain)

These are called by the main pipeline workflows using workflow_call.

How the Pull Request Workflow Works

When a contributor opens or updates a pull request targeting staging (or main), pull-request.yml runs a build-and-test matrix:

  1. Checks out the PR branch.
  2. Builds twice — once with the minimum supported Qt version and once with the maximum — to ensure compatibility across the supported Qt range.
  3. Runs tests via the reusable test workflow (without coverage uploads).
  4. Builds Doxygen documentation to verify it compiles without errors.

The PR cannot be merged until all matrix jobs pass. This ensures that every change is validated on Linux, macOS, and Windows before it reaches the staging branch.

How the Staging Workflow Works

staging.yml is the active development pipeline, triggered on every push to staging. It:

  • Creates or updates the dev_build pre-release on GitHub with the latest development binaries
  • Builds with both minimum and maximum Qt versions
  • Runs tests with code coverage — enforcing a minimum threshold (50%) and detecting coverage regressions
  • Invokes the platform-specific release workflows (release-linux.yml, release-macos.yml, release-windows.yml, release-installer.yml) to produce development binaries tagged as dev_build
  • Deploys the dev version of the documentation website to /dev/ and Doxygen API docs to /dev/
  • Runs CodeQL security analysis

How the Main / Release Workflow Works

main.yml handles two scenarios:

Pushes to main (no tag)

On every push to main, the workflow:

  • Builds with minimum and maximum Qt versions
  • Runs tests (with Codecov upload)
  • Deploys the stable website and Doxygen API documentation (preserving the dev subdirectory)

Tagged releases (v*)

When a version tag is pushed (e.g., v2.0.0), the workflow additionally:

  • Creates a GitHub Release from the tag
  • Invokes platform-specific release workflows to build and upload binaries for Linux, macOS, and Windows
  • Builds and uploads platform installers (.run, .dmg, .exe)
  • Builds and deploys WebAssembly applications
  • Uploads the Doxygen .qch file as a release asset

Each platform job follows the same high-level pattern: install Qt, configure CMake, build, deploy (bundle Qt libraries), package into an archive, and upload to the GitHub release.

Workflow File Structure

All workflow YAML files live in .github/workflows/ and follow a common structure:

name: WorkflowName

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

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-24.04, macos-26, windows-2025]
steps:
- uses: actions/checkout@v4
- name: Install Qt
# ...
- name: Configure
run: cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
- name: Build
run: cmake --build build --parallel
- name: Test
run: cd build && ctest --output-on-failure

Key elements include the trigger (on:), the matrix strategy for cross-platform builds, and the steps that install dependencies, compile, test, and optionally deploy.

Secrets and Environment Variables

Some workflows require GitHub repository secrets (configured in Settings → Secrets and variables → Actions):

SecretUsed byPurpose
GITHUB_TOKENAll release workflowsAutomatically provided; used to upload release assets
GH_PATRelease workflowsPersonal access token for cross-repo operations (optional fallback)
GIT_CREDENTIALSWebsite + Doxygen deployAuthentication for pushing to gh-pages branches
CODECOV_TOKENMain workflowToken for uploading coverage to Codecov
COVERITY_TOKENcoverity.ymlAuthentication token for Coverity Scan

Adding or Modifying a Workflow

To add a new workflow:

  1. Create a new .yml file in .github/workflows/.
  2. Define the trigger event (on:) — push, pull_request, schedule, or workflow_dispatch.
  3. Define one or more jobs with the appropriate runner (runs-on:) and steps.
  4. Test the workflow by pushing to a feature branch and opening a PR against staging.

To modify an existing workflow, edit the corresponding .yml file and push the change. If the modification affects the PR workflow, open a PR to see the results immediately.