Skip to content

Repository files navigation

🐍 Python Workflows

Linux FoundationLicense

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

WorkflowPurposeTrigger style
.github/workflows/build-test.yamlSingle-arch build, test, audit, SBOM and Grype scanPull request
.github/workflows/build-test-release.yamlSingle-arch pipeline plus tag validation, release artefact attachment and draft-release promotion (the caller performs PyPI publishing)Tag push
.github/workflows/build-test-multiarch.yamlMulti-architecture (x64 + arm64) variant with native build hooks for C-extension projectsPull request
.github/workflows/build-test-release-multiarch.yamlMulti-architecture release variantTag 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: readpull-requests: readuses: 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

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors