Reusable workflows that reduce maintenance effort.
I use tox to manage testing in my Python projects, and I use GitHub workflows to set up and execute tox.
This repo allows me to centralize most of my CI workflows so I only need to define a testing matrix in my other projects.
The tox.yaml
workflow in this repo has the following features:
- Configurable runners
- Multiple CPython/PyPy interpreter versions per runner
- Selectable tox environments
- Schema validation of the inputs passed to the workflow
- Built-in caching of tox and virtual environments with strong cache-busting
runner
: The runner to use.runner: "ubuntu-latest"
cpythons
: An array of CPython interpreter versions to install. Items must be strings.cpythons: - "3.11" - "3.12"
cpython-beta
: The CPython interpreter beta to install. Must be a string.Example:
cpython-beta: "3.13"
pypys
: An array of PyPy interpreter versions to install. Items must be strings.Example:
pypys: - "3.9" - "3.10"
tox
: Tox-related settings.tox.environments
: An array of tox environments to run. Items must be strings. Mutually-exclusive withtox.pre-environments
andtox.post-environments
.Example:
tox: environments: - "docs" - "mypy"
Resulting tox command:
tox run -e "docs,mypy"
tox.pre-environments
: An array of of tox environments to run before a generated list of all CPython and PyPy environments. Mutually-exclusive withtox.environments
.Example:
cpythons: - "3.11" pypys: - "3.10" tox: pre-environments: - "flake8"
Resulting tox command:
tox run -e "flake8,py3.11,pypy3.10"
tox.post-environments
: An array of of tox environments to run after a generated list of all CPython and PyPy environments. Mutually-exclusive withtox.environments
.Example:
cpythons: - "3.11" pypys: - "3.10" tox: post-environments: - "coverage"
Resulting tox command:
tox run -e "py3.11,pypy3.10,coverage"
cache
: Cache-related settings.cache.paths
: An array of additional paths to cache.By default, a virtual environment is created in
.venv/
with tox installed, and tox virtual environments are created when tox runs in.tox/
. These two directories are always cached and can be augmented bypaths
.Example:
cache: paths: - ".mypy_cache/"
Resulting
actions/cache
configuration:uses: "actions/cache@???" with: path: | .tox/ .venv/ .mypy_cache/
cache.key
: Cache key-related settings.cache.key.prefix
: The string prefix to use with the cache. Defaults to"tox"
.Example:
cache: key: prefix: "docs"
Resulting
actions/cache
configuration:uses: "actions/cache@???" with: key: "docs-..."
cache.key.hash-files
: An array of paths (or glob patterns) to hash and include in the cache key for cache-busting.Note that the existence of the path or glob patterns is validated; if paths do not exist, or the glob patterns match nothing, the workflow will fail.
Example:
cache: key: hash-files: - "pyproject.toml" - "requirements/*/*.txt"
Resulting
actions/cache
configuration:uses: "actions/cache@???" with: key: "...${{ hashFiles('.python-identifiers', '.workflow-config.json', 'tox.ini', '.hash-files.md5') }}"
The workflow requires a JSON-serialized input named "config"
.
The easiest way to accomplish this is by using a matrix configuration,
and using the toJSON()
function to serialize it as a workflow input:
strategy:
matrix:
runner: ["ubuntu-latest"]
cpythons: ["3.12"]
uses: "kurtmckee/github-workflows/.github/workflows/tox.yaml@v0.1"
with:
config: "${{ toJSON(matrix) }}"
jobs:
test:
strategy:
matrix:
runner:
- "ubuntu-latest"
- "macos-latest"
- "windows-latest"
# Use a nested list syntax with the "cpythons" key.
cpythons:
- - "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
# Test a beta CPython version.
cpython-beta:
- "3.13"
# Use a nested list syntax with the "pypys" key.
pypys:
- - "3.8"
- "3.9"
- "3.10"
uses: "kurtmckee/github-workflows/.github/workflows/tox.yaml@v0.1"
with:
config: "${{ toJSON(matrix) }}"
jobs:
test:
strategy:
matrix:
runner:
- "ubuntu-latest"
cpythons:
- - "3.11"
- "3.12"
include:
- runner: "ubuntu-latest"
cpythons:
- "3.12"
tox:
environments:
- "docs"
- "mypy"
uses: "kurtmckee/github-workflows/.github/workflows/tox.yaml@v0.1"
with:
config: "${{ toJSON(matrix) }}"
jobs:
test:
strategy:
matrix:
config:
# Test all Python versions on Ubuntu.
- runner: "ubuntu-latest"
cpythons:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
# Test only the highest and lowest Pythons on Windows.
- runner: "windows-latest"
cpythons:
- "3.8"
- "3.12"
uses: "kurtmckee/github-workflows/.github/workflows/tox.yaml@v0.1"
with:
config: "${{ toJSON(matrix.config) }}"