Sitelet https://github.com/Dagitali/python-project-lifecycle
Skip to content

Repository files navigation

python-project-lifecycle

python-project-lifecycle is a composite GitHub Action for common Python project lifecycle phases, one phase per run. It standardizes step behavior for Python project automation while leaving workflow topology, permissions, matrices, environments, and deployment approvals in the caller's workflow.

Usage

Build, validate, smoke-test, and upload Python distributions:

- uses: Dagitali/python-project-lifecycle@v0.1.0
  with:
    phase: build-upload
    python-version: '3.13'
    release-artifact-audit-command: python tools/check_release_artifacts.py dist/*
    behavior-smoke-command: '{python} tools/smoke_test_schema_validation.py {python}'
    command-name: my-command
    package-name: my-package
    smoke-commands: |
      my-command --version
      my-command --help

Build Sphinx documentation:

- uses: Dagitali/python-project-lifecycle@v0.1.0
  with:
    phase: docs
    python-version: '3.13'
    docs-builder: html

Run a caller-provided security command:

- uses: Dagitali/python-project-lifecycle@v0.1.0
  with:
    phase: security
    pip-install: 'pip-audit'
    security-command: pip-audit

Inputs

The Required column reflects the action metadata in action.yml. Some inputs with defaults are still required for specific phases at runtime, as noted in the descriptions below.

Name Required Default Description
phase Yes N/A Lifecycle phase to run: bootstrap, lint, format-check, test, typecheck, doclint, docs, sbom, security, build, build-upload, upload-dist, download-dist, wheel-smoke, installer-smoke, or deploy.
python-version No 3.13 Python version passed to Dagitali/python-bootstrap, which provisions Python through actions/setup-python.
pip-install No '' Arguments passed to python -m pip install for most bootstrapped phases. Ignored for build, build-upload, docs, upload-dist, and download-dist.
pip-version No '' Exact pip version to install instead of upgrading to latest.
upgrade-pip No true Upgrade pip to latest unless pip-version is set.
working-directory No . Directory where shell commands run.
ruff-args No check . Arguments passed to ruff for the lint phase.
format-check-command No '' Command run by the format-check phase. Required when phase is format-check.
meta-test-command No '' Optional command run before pytest-args in the test phase.
pytest-args No -q tests/ Arguments passed to pytest in the test phase.
typecheck-command No mypy . Command run by the typecheck phase.
doclint-command No '' Command run by the doclint phase. Required when phase is doclint.
security-command No '' Command run by the security phase. Required when phase is security.
docs-builder No html Sphinx builder used by the docs phase.
docs-source-dir No docs/source Sphinx source directory used by the docs phase. The directory must exist.
docs-build-dir No docs/build Sphinx build output root used by the docs phase.
docs-doctree-dir No docs/build/doctrees Sphinx doctree output root used by the docs phase.
docs-generated-api-dir No docs/source/api/generated Existing generated API .rst files deleted before the docs phase.
docs-pip-install No -e .[docs] Dependency install arguments used instead of pip-install for the docs phase.
build-command No python -m build Command used by the build and build-upload phases to build distributions.
release-artifact-audit-command No '' Optional caller-owned command used by build phases to audit release artifacts.
twine-check No true Run python -m twine check during build phases.
build-pip-install No build twine Dependency install arguments used instead of pip-install for build and build-upload.
skip-installer-smoke No false Skip installer smoke tests during build-upload.
skip-wheel-smoke No false Skip wheel behavior smoke tests during build-upload.
skip-artifact-upload No false Skip distribution artifact upload during build-upload.
dist-glob No dist/* Glob or path expression used to select built distributions.
artifact-name No dist-artifacts Artifact name used when uploading or downloading distributions.
artifact-path No dist Destination path for downloaded artifacts.
sbom-tool-version No 7.2.2 CycloneDX tool version installed by the sbom phase.
sbom-output-file No sbom.json SBOM output path.
sbom-output-format No JSON SBOM output format.
sbom-command No '' Optional custom command run by the sbom phase instead of the default generator.
wheel-glob No dist/*.whl Glob or path for the built wheel artifact used by smoke tests.
smoke-venv-path No .wheel-venv Virtual environment path used by wheel-smoke and the delegated pip installer smoke check.
behavior-smoke-command No '' Command run after installing the wheel in wheel-smoke. Use {python} as the smoke-test interpreter placeholder. Required for wheel-smoke and for build-upload unless wheel smoke is skipped.
command-name No '' Command expected to be available on PATH after installing the wheel artifact. Required for installer-smoke and for build-upload unless installer smoke is skipped.
smoke-commands No '' Newline-separated commands passed to the delegated installer smoke action. Required for installer-smoke and for build-upload unless installer smoke is skipped.
installer-smoke-installers No pip,pipx,uv Comma-separated installers to smoke-test. Supported values are pip, pipx, and uv.
package-name No '' Package name passed to installer smoke tests for cleanup when the distribution package name differs from command-name.
deploy-command No '' Command run by the deploy phase. Required when phase is deploy.

Examples

Run linting with Ruff:

- uses: Dagitali/python-project-lifecycle@v0.1.0
  with:
    phase: lint
    python-version: '3.13'
    pip-install: ruff
    ruff-args: check src tests

Run tests with an optional setup command:

- uses: Dagitali/python-project-lifecycle@v0.1.0
  with:
    phase: test
    python-version: '3.13'
    pip-install: '-e .[test]'
    meta-test-command: python -m compileall src
    pytest-args: '-q tests/'

Generate an SBOM:

- uses: Dagitali/python-project-lifecycle@v0.1.0
  with:
    phase: sbom
    python-version: '3.13'
    sbom-output-file: sbom.json

Download distribution artifacts in a later job:

- uses: Dagitali/python-project-lifecycle@v0.1.0
  with:
    phase: download-dist
    artifact-name: dist-artifacts
    artifact-path: dist

Deploy with a caller-owned command:

- uses: Dagitali/python-project-lifecycle@v0.1.0
  with:
    phase: deploy
    deploy-command: python tools/deploy.py

Behavior

Set phase to select exactly one lifecycle operation:

Phase Behavior
bootstrap Installs the requested Python version and pip dependencies, then captures Python and pip output metadata.
lint Bootstraps Python, prints the Ruff version, and runs ruff with ruff-args.
format-check Bootstraps Python and runs format-check-command.
test Bootstraps Python, optionally runs meta-test-command, then runs pytest with pytest-args.
typecheck Bootstraps Python and runs typecheck-command.
doclint Bootstraps Python and runs doclint-command.
docs Bootstraps Python with docs-pip-install, removes stale generated API .rst files when present, clears the selected builder output and doctree directories, and runs Sphinx with warnings treated as errors.
sbom Bootstraps Python and generates an environment SBOM with cyclonedx-py, or runs sbom-command when provided. The default generator currently uses POSIX virtual environment paths; use sbom-command for Windows runners.
security Bootstraps Python and runs security-command.
build Bootstraps Python with build-pip-install, runs build-command, optionally runs release-artifact-audit-command, then optionally runs python -m twine check against dist-glob.
build-upload Runs the build behavior, then wheel smoke tests, installer smoke tests, and artifact upload unless the corresponding skip inputs are set.
upload-dist Uploads dist-glob as artifact-name without bootstrapping Python.
download-dist Downloads artifact-name to artifact-path without bootstrapping Python.
wheel-smoke Creates a temporary virtual environment, installs the selected wheel, and runs behavior-smoke-command.
installer-smoke Delegates installer validation to Dagitali/python-installer-smoke, testing the selected wheel with pip, pipx, and/or uv.
deploy Bootstraps Python and runs deploy-command.

Most command-valued inputs are executed as trusted shell snippets in the configured working-directory. smoke-commands is passed through to the delegated Dagitali/python-installer-smoke action rather than run directly by this action. Empty command inputs are rejected for phases that require a caller-provided command.

The skip-artifact-upload, skip-installer-smoke, and skip-wheel-smoke inputs are validated on every run and must be exactly true or false. The twine-check input must be exactly true or false for build and build-upload.

The action composes pinned public actions for Python bootstrapping, installer smoke testing, artifact upload, and artifact download. It also uses helper scripts in scripts/ through GITHUB_ACTION_PATH.

Security Notes

Treat all command inputs, path and glob inputs, dependency install arguments, and smoke-test command inputs as trusted workflow configuration. Do not build these values from untrusted issue, pull request, or user-supplied text.

The command inputs are shell commands. Keep smoke and validation commands small and deterministic, such as --version, --help, import checks, metadata checks, or lightweight startup behavior checks.

This action pins the public actions it composes by commit SHA. Calling workflows should still pin this action to a release tag or full commit SHA.

Outputs

Outputs mostly mirror the configured paths. upload-dist and download-dist do not bootstrap Python, so python-version and pip-version reflect whatever Python is already available on the runner, or an empty value if none is found.

Name Description
python-version Resolved Python version reported by python --version.
pip-version Resolved pip version reported by python -m pip --version.
dist-path Distribution artifact path or glob used for upload and validation.
artifact-path Destination path used when downloading distribution artifacts.
artifact-name Uploaded or downloaded artifact name.
wheel-path Wheel artifact path or glob used by smoke tests.
docs-output-dir Built documentation output directory.
sbom-path Generated SBOM path.
coverage-file Conventional coverage report path, coverage.xml. The action exposes this path but does not generate coverage by itself.

Permissions

The action itself does not require repository or token permissions. Calling workflows should grant only the permissions needed by their own jobs, such as contents: read for checkout, package publishing permissions, or deployment environment permissions.

Version Pinning

Prefer a release tag such as Dagitali/python-project-lifecycle@v0.1.0 or an exact version tag for normal use. Pin to a full commit SHA when your workflow requires maximum supply-chain immutability.

License

Copyright © 2026 Dagitali LLC. All rights reserved.

See LICENSE for details.

About

A composite GitHub Action for common Python project lifecycle phases.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages