All skills
github avatar

/python-pypi-package-builder

@49fd3f3 official
by githubgithub/awesome-copilot40k stars
5,040

End-to-end skill for building, testing, linting, versioning, and publishing a production-grade Python library to PyPI. Covers all four build backends (setuptools+setuptools_scm, hatchling, flit, poetry), PEP 440 versioning, semantic versioning, dynamic git-tag versioning, OOP/SOLID design, type hints (PEP 484/526/544/561), Trusted Publishing (OIDC), and the full PyPA packaging flow. Use for: creating Python packages, pip-installable SDKs, CLI tools, framework plugins, pyproject.toml setup, py.typed, setuptools_scm, semver, mypy, pre-commit, GitHub Actions CI/CD, or PyPI publishing.

Use this Skill: https://skilld.dev/gh/github/awesome-copilot/python-pypi-package-builder

This session only. Nothing lands on disk.

referencesci-publishing.md

≈2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

CI/CD, Publishing, and Changelog

Table of Contents

  1. Changelog format
  2. ci.yml — lint, type-check, test matrix
  3. publish.yml — triggered on version tags
  4. PyPI Trusted Publishing (no API tokens)
  5. Manual publish fallback
  6. Release checklist
  7. Verify py.typed ships in the wheel
  8. Semver change-type guide

1. Changelog Format

Keep a CHANGELOG.md following Keep a Changelog conventions. Every PR should update the [Unreleased] section. Before releasing, move those entries to a new version section with the date.

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---

## [Unreleased]

### Added
- (in-progress features go here)

---

## [1.0.0] - 2026-04-02

### Added
- Initial stable release
- `YourMiddleware` with gradual, strict, and combined modes
- In-memory backend (no extra deps)
- Optional Redis backend (`pip install pkg[redis]`)
- Per-route override via `Depends(RouteThrottle(...))`
- `py.typed` marker — PEP 561 typed package
- GitHub Actions CI: lint, mypy, test matrix, Trusted Publishing

### Changed
### Fixed
### Removed

---

## [0.1.0] - 2026-03-01

### Added
- Initial project scaffold

[Unreleased]: https://github.com/you/your-package/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/you/your-package/compare/v0.1.0...v1.0.0
[0.1.0]: https://github.com/you/your-package/releases/tag/v0.1.0

Semver — what bumps what

Change type Bump Example
Breaking API change MAJOR 1.0.0 → 2.0.0
New feature, backward-compatible MINOR 1.0.0 → 1.1.0
Bug fix PATCH 1.0.0 → 1.0.1

2. ci.yml

Runs on every push and pull request. Tests across all supported Python versions.

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

jobs:
  lint:
    name: Lint, Format & Type Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Install dev dependencies
        run: pip install -e ".[dev]"
      - name: ruff lint
        run: ruff check .
      - name: ruff format check
        run: ruff format --check .
      - name: mypy
        run: |
          if [ -d "src" ]; then
              mypy src/
          else
              mypy {mod}/
          fi

  test:
    name: Test (Python ${{ matrix.python-version }})
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13"]

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0    # REQUIRED for setuptools_scm to read git tags

      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: pip install -e ".[dev]"

      - name: Run tests with coverage
        run: pytest --cov --cov-report=xml

      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          fail_ci_if_error: false

  test-redis:
    name: Test Redis backend
    runs-on: ubuntu-latest
    services:
      redis:
        image: redis:7-alpine
        ports: ["6379:6379"]
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Install with Redis extra
        run: pip install -e ".[dev,redis]"

      - name: Run Redis tests
        run: pytest tests/test_redis_backend.py -v

Always add fetch-depth: 0 to every checkout step when using setuptools_scm. Without full git history, setuptools_scm can't find tags and the build fails with a version detection error.


3. publish.yml

Triggered automatically when you push a tag matching v*.*.*. Uses Trusted Publishing (OIDC) — no API tokens in repository secrets.

# .github/workflows/publish.yml
name: Publish to PyPI

on:
  push:
    tags:
      - "v*.*.*"

jobs:
  build:
    name: Build distribution
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0      # Critical for setuptools_scm

      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Install build tools
        run: pip install build twine

      - name: Build package
        run: python -m build

      - name: Check distribution
        run: twine check dist/*

      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

  publish:
    name: Publish to PyPI
    needs: build
    runs-on: ubuntu-latest
    environment: pypi
    permissions:
      id-token: write     # Required for Trusted Publishing (OIDC)

    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/

      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1

4. PyPI Trusted Publishing

Trusted Publishing uses OpenID Connect (OIDC) so PyPI can verify that a publish came from your specific GitHub Actions workflow — no long-lived API tokens required, no rotation burden.

One-time setup

  1. Create an account at https://pypi.org
  2. Go to Account → Publishing → Add a new pending publisher
  3. Fill in:
    • GitHub owner (your username or org)
    • Repository name
    • Workflow filename: publish.yml
    • Environment name: pypi
  4. Create the pypi environment in GitHub: repo → Settings → Environments → New environment → name it pypi

That's it. The next time you push a v*.*.* tag, the workflow authenticates automatically.


5. Manual Publish Fallback

If CI isn't set up yet or you need to publish from your machine:

pip install build twine

# Build wheel + sdist
python -m build

# Validate before uploading
twine check dist/*

# Upload to PyPI
twine upload dist/*

# OR test on TestPyPI first (recommended for first release)
twine upload --repository testpypi dist/*
pip install --index-url https://test.pypi.org/simple/ your-package
python -c "import your_package; print(your_package.__version__)"

6. Release Checklist

[ ] All tests pass on main/master
[ ] CHANGELOG.md updated — move [Unreleased] items to new version section with date
[ ] Update diff comparison links at bottom of CHANGELOG
[ ] git tag vX.Y.Z
[ ] git push origin master --tags
[ ] Monitor GitHub Actions publish.yml run
[ ] Verify on PyPI: pip install your-package==X.Y.Z
[ ] Test the installed version:
    python -c "import your_package; print(your_package.__version__)"

7. Verify py.typed Ships in the Wheel

After every build, confirm the typed marker is included:

python -m build
unzip -l dist/your_package-*.whl | grep py.typed
# Must print: your_package/py.typed
# If missing, check [tool.setuptools.package-data] in pyproject.toml

If it's missing from the wheel, users won't get type information even though your code is fully typed. This is a silent failure — always verify before releasing.


8. Semver Change-Type Guide

Change Version bump Example
Breaking API change (remove/rename public symbol) MAJOR 1.2.3 → 2.0.0
New feature, fully backward-compatible MINOR 1.2.3 → 1.3.0
Bug fix, no API change PATCH 1.2.3 → 1.2.4
Pre-release suffix 2.0.0a1 → 2.0.0rc1 → 2.0.0
Packaging-only fix (no code change) post-release 1.2.3 → 1.2.3.post1

Source: SKILL.md on GitHub

No alerts10d4 checks · Risk SAFE
  • Gen Agent Trust Hub10d

    This skill provides a comprehensive and secure framework for building, testing, and publishing Python packages following industry best practices. It incorporates secure publishing via OpenID Connect (OIDC), uses modern and efficient tooling like Ruff, and provides a local scaffolding script that follows standard templating procedures. All external references and dependencies target well-known and trusted organizations within the Python and GitHub ecosystems.

  • Socket10d

    No alerts

  • Snyk10d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 49fd3f3. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 6 months ago
  • Python
  • pypi
  • packaging
  • setuptools
  • hatchling
  • flit
  • poetry
  • versioning
  • ci-cd
  • github-actions

README badge

README badge for github/awesome-copilot/python-pypi-package-builder

Covers the full PyPI publishing pipeline for Python packages: build backend selection (setuptools+setuptools_scm, hatchling, flit, poetry), project structure (src/ vs flat), type hints, testing, versioning (PEP 440 / semver / git-tag), and GitHub Actions CI/CD with Trusted Publishing. Targets teams building pip-installable libraries, SDKs, CLI tools, or framework plugins.

Generated from the current SKILL.md.

Which build backend should I use?
Use setuptools + setuptools_scm if you want version derived from git tags. Use hatchling or flit for pure-Python projects without git-tag versioning. Use poetry v2+ if you want an all-in-one tool. Use setuptools only if you have C/Cython extensions.
Does this skill support publishing with Trusted Publishing (OIDC)?
Yes. The skill covers Trusted Publishing setup in the CI/publishing workflow references and includes GitHub Actions templates for OIDC-based PyPI publishing.
What folder structure should I use for a new package?
Use src/ layout as the default for new projects — it prevents accidental imports of uninstalled code and is PyPA-recommended. Use flat layout only for single-purpose packages with 1–4 modules.
Does this cover type hints and mypy configuration?
Yes. The skill includes PEP 484/526/544/561 type hint patterns, py.typed marker file setup, and complete mypy configuration in the testing and quality reference.
Can I use this skill for CLI tools, SDKs, and plugins?
Yes. The skill covers all package types including utility libraries, API clients/SDKs, CLI tools, framework plugins, and data processing libraries, with patterns and entry-point configuration for each.

Generated from the current SKILL.md. These answers refresh after source changes.