Reusable composite GitHub Actions for Python CI/CD workflows. Cross-platform (Windows, macOS, Linux), supporting pip, uv, and pixi package managers.
📚 Full documentation: https://serapeum-org.github.io/github-actions/
The docs site (built with MkDocs + mike versioning, deployed from this repo) covers every action in depth — inputs, outputs, examples, and the consumer contract for each. This README is a top-level index.
Set up Python with your preferred package manager, install dependencies,
and configure caching. All three share the same install-groups input shape
(PEP 735 groups and/or extras) and lock-file verification defaults.
| Action | Usage | Guide | Reference |
|---|---|---|---|
| pip | serapeum-org/github-actions/actions/python-setup/pip@pip/v1.1.2 |
guide | reference |
| uv | serapeum-org/github-actions/actions/python-setup/uv@uv/v1.2.2 |
guide | reference |
| pixi | serapeum-org/github-actions/actions/python-setup/pixi@pixi/v1.2.2 |
guide | reference |
| Action | Usage | Guide | Reference |
|---|---|---|---|
| mkdocs-deploy | serapeum-org/github-actions/actions/mkdocs-deploy@mkdocs/v1.3.2 |
guide | reference |
mkdocs-deploy builds and publishes a versioned MkDocs site to GitHub Pages
via mike. Version deployed is selected
by the trigger input — pull_request → develop, main → main
(default), release → the tagged version (with a configurable alias, e.g.
latest).
New in mkdocs/v1.2.0 — notebooks-exclude and notebooks-continue-on-error
skip or tolerate notebooks that can't run in a clean CI runner (live data,
missing extras, flaky), so one failing notebook no longer aborts the deploy.
Built on the opt-in notebook execution with caching added in mkdocs/v1.1.0:
set notebooks-path: 'docs/notebook' and the action will walk your notebook
tree, restore .jupyter_cache/ from actions/cache (keyed on notebook
contents + src/**/*.py + pyproject.toml), preflight that
jupyter/nbconvert/ipykernel are importable, execute uncached notebooks
via jupyter nbconvert --execute, and feed the populated outputs into
mkdocs-jupyter (which runs with execute: false). Omitting notebooks-path
(the default) skips notebook execution entirely — zero behaviour change for
existing consumers. See the notebook-execution
section of the guide for the
consumer contract (required deps, mkdocs-jupyter config, src-layout
assumption, concrete pyproject.toml snippet).
| Action | Usage | Guide | Examples |
|---|---|---|---|
| GitHub Release | serapeum-org/github-actions/actions/release/github@github-release/v1.5.1 |
guide | examples |
| PyPI Release | serapeum-org/github-actions/actions/release/pypi@pypi-release/v1.0.4 |
guide | examples |
The release/github action automates version bumping via
Commitizen, writes the
changelog incrementally from the source of truth, creates a git tag, and
publishes a GitHub Release whose body is extracted directly from the
changelog (so release notes and project changelog stay in sync).
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: serapeum-org/github-actions/actions/python-setup/uv@uv/v1.2.2
with:
python-version: '3.12'
install-groups: 'groups: dev test'
- run: pytestDeploy docs (with notebook execution) on every PR, main push, and release:
- uses: serapeum-org/github-actions/actions/mkdocs-deploy@mkdocs/v1.3.2
with:
trigger: ${{ github.event_name }}
deploy-token: ${{ secrets.GITHUB_TOKEN }}
notebooks-path: 'docs/notebook'The install-groups input (for pip and uv) supports:
# PEP 735 dependency groups
install-groups: 'groups: dev test'
# Optional dependencies (extras)
install-groups: 'extras: aws viz'
# Both combined
install-groups: 'groups: dev, extras: aws'For pixi, use the environments input instead:
environments: 'default py312'Each action is versioned independently with namespaced tags:
pip/v1.1.2 # Python setup with pip
uv/v1.2.2 # Python setup with uv
pixi/v1.2.2 # Python setup with pixi
mkdocs/v1.3.2 # MkDocs deploy
github-release/v1.5.1 # GitHub release via Commitizen
pypi-release/v1.0.4 # PyPI release
Pin to an exact version, or to its commit SHA for supply-chain hardening.
There are no rolling/moving …/v1 tags; always pin an exact version:
# Exact version (recommended)
uses: serapeum-org/github-actions/actions/python-setup/uv@uv/v1.2.2
# Commit SHA (most strict)
uses: serapeum-org/github-actions/actions/python-setup/uv@6c0a569b67c149c4648c75495544732cba2d0eca # uv/v1.2.2For SHA-based pinning, here is the latest release of each action and the commit it points to. Update these when you cut a new tag.
| Action | Latest version | Commit SHA |
|---|---|---|
actions/python-setup/pip |
pip/v1.1.2 |
6c0a569b67c149c4648c75495544732cba2d0eca |
actions/python-setup/uv |
uv/v1.2.2 |
6c0a569b67c149c4648c75495544732cba2d0eca |
actions/python-setup/pixi |
pixi/v1.2.2 |
6c0a569b67c149c4648c75495544732cba2d0eca |
actions/mkdocs-deploy |
mkdocs/v1.3.2 |
961524686fb512c05ca8e4c7bfe81ba68eef4dda |
actions/release/github |
github-release/v1.5.1 |
961524686fb512c05ca8e4c7bfe81ba68eef4dda |
actions/release/pypi |
pypi-release/v1.0.4 |
961524686fb512c05ca8e4c7bfe81ba68eef4dda |
To verify locally: git rev-parse <tag>^{commit} (the ^{commit} is
required — git rev-parse <tag> returns the annotated-tag object SHA, not
the commit it points at).
See the Versioning Guide for release workflow, tag conventions, and breaking-change policy.
- Hosted docs: https://serapeum-org.github.io/github-actions/ (MkDocs,
versioned via mike — includes
latest,main, and per-release tags). - In-repo guides: under
docs/— same content as the hosted site. - Action reference pages: auto-generated from each
action.ymlintodocs/reference/byscripts/generate_action_docs.py(runs in CI on every push tomainthat changes an action). - Getting Started: docs/getting-started.md.
- Read the test workflows in
.github/workflows/test-*.ymlto understand how each action is exercised. - Use test fixtures under
tests/data/— never hand-roll inline fixtures. - Maintain cross-platform compatibility (
shell: bash, forward-slash paths, string-typed booleans). - Every test job that invokes an action whose code path can reach
git push,mike deploy,gh release create, or PyPI upload MUST call./.github/workflows/test-helpers/setup-fake-remotebetweenactions/checkoutand the first action invocation — pushes must never escape to the real GitHub repo. - Follow semantic versioning: new optional input = MINOR; behaviour-preserving fix or docs = PATCH; removed/renamed input or changed default behaviour = MAJOR.
See LICENSE for details.