Skip to main content

Template library demonstrating Python package release CI/CD

Project description

test-python-package-release

Template repository demonstrating a complete CI/CD pipeline for Python packages published to PyPI.

Quick start

uv sync --group dev
uv run pytest

Project layout

.
├── .github/workflows/   # CI, Claude review, release-please, publish
├── src/                 # library code (src/ layout)
├── tests/               # pytest tests
├── pyproject.toml       # single source of truth: build, deps, ruff, pytest, tox
├── .pre-commit-config.yaml
├── commitlint.config.cjs
└── CHANGELOG.md         # managed by release-please

Development

# Install hooks (runs ruff + ty pre-commit, conventional commit-msg)
uv run pre-commit install --hook-type pre-commit --hook-type commit-msg

# Run the full test matrix (3.11, 3.12, 3.13)
uv run tox

# Single env
uv run tox -e py313 -- -k calculator

# Lint / format check / type check
uv run ruff check .
uv run ruff format --check .
uv run ty check src

Commits

Every commit MUST follow the Conventional Commits specification.

Examples:

  • feat: add support for negative numbers
  • fix(calculator): correct divide by zero error
  • chore(deps): bump ruff to 0.9
  • feat!: drop Python 3.10 support (breaking change → major bump)

Enforced locally by conventional-pre-commit (commit-msg hook) and in CI by commitlint.

Release flow

PR opened ──▶ ci.yml (lint, ty, pytest matrix, commitlint)
                │
                └─ optional: comment "@claude" ──▶ claude-review.yml

PR merged ──▶ main ──▶ release-please.yml
                          │
                          └─ creates/updates a "Release PR"
                             (bumps version, regenerates CHANGELOG)

Release PR merged ──▶ release-please tags + creates GitHub Release
                          │
                          └─ publish.yml ──▶ uv build
                                            ──▶ TestPyPI (OIDC)
                                            ──▶ PyPI (OIDC, gated env)

First-time setup after cloning the template

  1. Rename the package: update name in pyproject.toml, the directory under src/, and imports in tests/. Also update the package-name and extra-files paths in .github/release-please-config.json.

  2. Workflow permissions: Settings → Actions → General → Workflow permissions. Enable:

    • "Read and write permissions"
    • "Allow GitHub Actions to create and approve pull requests"
  3. Personal Access Token for release-please: create a fine-grained PAT (generate here) scoped to this repo with Contents: read+write, Pull requests: read+write, Workflows: read+write. Add as repository secret RELEASE_PLEASE_TOKEN. (Required so the GitHub Release created by release-please triggers the publish.yml workflow — events from the default GITHUB_TOKEN do not trigger other workflows.)

  4. Install the Claude Code GitHub App at github.com/apps/claude and grant access to this repo. Add ANTHROPIC_API_KEY repository secret.

  5. Configure Trusted Publishers on PyPI and TestPyPI for your repo. Use "pending publisher" if the project doesn't exist yet. Point each to:

    • Workflow name: publish.yml
    • Environment name: pypi (production) and testpypi respectively
  6. Create GitHub Environments testpypi and pypi under Settings → Environments. For each, under Deployment branches and tags:

    • Select "Selected branches and tags"
    • Add a branch rule: main
    • Add a tag rule (toggle ref type to "Tag" in the modal): use the tag pattern that release-please produces — by default <package-name>-v* (e.g. test-python-package-release-v*)
  7. (Optional) Branch protection ruleset for main:

    • Require a PR before merging
    • Require status checks: lint, test (3.11), test (3.12), test (3.13), commitlint
    • Block force pushes, restrict deletions
    • Add yourself to the bypass list so you can merge release-please PRs
  8. (Optional) Production gate for PyPI publishing — on Pro/Team/Enterprise plans only: add a Required reviewer on the pypi environment to require manual approval before production publish.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

test_python_package_release-0.3.1.tar.gz (46.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

test_python_package_release-0.3.1-py3-none-any.whl (5.7 kB view details)

Uploaded Python 3

File details

Details for the file test_python_package_release-0.3.1.tar.gz.

File metadata

File hashes

Hashes for test_python_package_release-0.3.1.tar.gz
Algorithm Hash digest
SHA256 88ee1d0790b6897e8c57fc499bb419a4c12b885e30e3149ecfed028d9dc2334e
MD5 e7a1a949ff3e45806b7f68991e9dd74a
BLAKE2b-256 cece26312aba04f5c0fae4f2a2210c3de4753ea95235a46686766eb3679fc237

See more details on using hashes here.

Provenance

The following attestation bundles were made for test_python_package_release-0.3.1.tar.gz:

Publisher: publish.yml on wozniakos10/test_python_package_release

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file test_python_package_release-0.3.1-py3-none-any.whl.

File metadata

File hashes

Hashes for test_python_package_release-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 61d06250a6233ec7e3f1254c81f2173f48f2b12235e8ce30b88fdb56727046ff
MD5 f70356688c1a229906f1f04d69fc43e3
BLAKE2b-256 f9a112a88ec4bacfa78d1f566f2d2f55ae505d26515e97600f30ff8ab8d7acd9

See more details on using hashes here.

Provenance

The following attestation bundles were made for test_python_package_release-0.3.1-py3-none-any.whl:

Publisher: publish.yml on wozniakos10/test_python_package_release

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page