Skip to content

Repository files navigation

🐍 Python Workflows

Linux Foundation License

Reusable GitHub Actions workflows that encapsulate the canonical Linux Foundation Python build / test / release pipeline. Adopt them from a thin caller workflow instead of copying hundreds of lines of pipeline YAML into every Python repository.

Reusable workflows

Workflow Purpose Trigger style
.github/workflows/build-test.yaml Single-arch build, test, audit, SBOM and Grype scan Pull request
.github/workflows/build-test-release.yaml Single-arch pipeline plus tag validation, release artefact attachment and draft-release promotion (the caller performs PyPI publishing) Tag push
.github/workflows/build-test-multiarch.yaml Multi-architecture (x64 + arm64) variant with native build hooks for C-extension projects Pull request
.github/workflows/build-test-release-multiarch.yaml Multi-architecture release variant Tag push

Each pipeline runs a repository-metadata job in parallel (an informational step that does not gate the build). After python-build, the test, audit and SBOM/Grype branches run in parallel - none gates another, so a pull request surfaces every failure at once (jobs in { } run concurrently; -> denotes sequence):

python-build -> { python-tests | python-audit | sbom -> grype }

The release variants wrap this with tag-validate up front and a release-promotion chain at the end. They also defer python-tests until python-audit and grype have both passed, so a failing audit skips the expensive test matrix and never reaches release promotion:

python-build -> { python-audit | sbom -> grype } -> python-tests
  -> attach-artefacts -> promote-release

PyPI publishing is the caller's responsibility

The release variants do not publish to PyPI. PyPI trusted publishing matches the OIDC job_workflow_ref claim against the calling repository, so a reusable workflow can never act as a trusted publisher (see the PyPI docs). To keep trusted publishing (and the PEP 740 attestations it enables), the caller must run the publish jobs itself, stacked after the reusable call:

caller: release (reusable) -> test-pypi -> pypi

The reusable workflow exposes a tag output and leaves the run-scoped build artefact in place, so the caller's publish jobs have everything they need. See examples/build-test-release/ for a complete caller.

The multi-arch variants add a python-metadata job and fan the build, test and audit jobs across an architecture matrix.

Usage

Copy a template from examples/ into your project's .github/workflows/ directory and replace the placeholder uses: SHA with a pinned release of this repository. Each workflow ships in two forms:

  • github.yaml — a plain GitHub-native caller (pull-request or tag-push triggered).
  • gerrit.yaml — a Gerrit-wrapped caller for projects where Gerrit is the source of truth (SCM), integrating with gerrit_to_platform voting.
examples/
  build-test/                    { github.yaml, gerrit.yaml }
  build-test-release/            { github.yaml, gerrit.yaml }
  build-test-multiarch/          { github.yaml, gerrit.yaml }
  build-test-release-multiarch/  { github.yaml, gerrit.yaml }

A minimal caller looks like this:

jobs:
  build-test:
    permissions:
      contents: read
      pull-requests: read
    uses: lfreleng-actions/python-workflows/.github/workflows/build-test.yaml@<release-sha>

All inputs are optional and default to the canonical behaviour; see the inputs: block at the top of each workflow file for the full, documented list (project layout, matrix override, tox, pytest, audit allow-lists, SBOM options, Grype severity gate, runner hardening, and Gerrit-aware checkout).

Gerrit support

The reusable workflows are Gerrit-aware: when a caller sets the gerrit_refspec input they check out the unmerged change with checkout-gerrit-change-action instead of actions/checkout. Vote casting lives in the gerrit.yaml caller examples (clear vote → run → report vote), gated by a GERRIT_DISABLED toggle on the build-test workflows so they can also run manually from the GitHub UI. See the gerrit.yaml examples for the full pattern.

Testing

.github/workflows/testing.yaml exercises the reusable workflows against three large downstream consumers (dependamerge, lftools-uv and python-nss-ng) in parallel, validating the workflows end-to-end on every pull request.

Design

See docs/BRIEF.md for the full design rationale and the decisions behind the input surface, Gerrit integration, harden-runner strategy and multi-architecture structure.

About

GitHub workflows for Python projects

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors