Skip to content

Prep v0.2.2

Prep v0.2.2 #10

Workflow file for this run

# .github/workflows/release.yml
name: Release (PyPI)
# WHY: Publish a tagged release to PyPI and create a GitHub Release.
# REQ: Trigger ONLY on version tags like v1.2.3.
# REQ: PyPI project must be configured for Trusted Publishing (OIDC).
on:
push:
tags:
- "v*.*.*" # WHY: Trigger on version tags like 'vx.y.z'.
permissions: # WHY: Use least privileges required.
contents: write # WHY: Create GitHub Release + push gh-pages for mike
id-token: write # WHY: PyPI Trusted Publishing (OIDC)
env:
PYTHONUNBUFFERED: "1" # WHY: Real-time logging.
PYTHONIOENCODING: "utf-8" # WHY: Ensure UTF-8 encoding so docs with international characters work.
UV_PYTHON: "3.14"
jobs:
build-and-release:
runs-on: ubuntu-latest
timeout-minutes: 30
environment: pypi # WHY: Use 'pypi' environment for PyPI publishing; ignore warnings.
steps:
# === ASSEMBLE ===
- name: A1) Checkout this repository with full history and tags
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
ref: ${{ github.ref }}
- name: A2) Install uv (with caching and uv.lock awareness)
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: A3) Install Python 3.14
run: uv python install 3.14
- name: A4) Display versions
run: |
uv --version
uv run python --version
- name: A5) Sync to install all dependencies (frozen)
# REQ: dev extra SHOULD include ruff/pyright/pytest/deptry (as used below).
# REQ: docs extra MUST include project documentation toolchain.
run: |
uv sync --extra dev --extra docs --frozen
# === BASELINE CHECKS (VALIDATE ONLY) ===
- name: B1) Ruff format (check only)
run: uv run ruff format --check .
- name: B2) Ruff lint (no fixes)
run: uv run ruff check .
- name: B3) Validate project.toml
run: uv run validate-pyproject pyproject.toml
- name: B4) Pyright (type check)
run: uv run pyright
# === DEPLOY (BUILD, RELEASE, DOCS, PACKAGE) ===
- name: D1) Extract plain version from tag (no leading 'v')
id: ver
shell: bash
run: echo "plain=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: D2) Build sdist + wheel
run: uv build
- name: D3) Ensure built artifact version matches tag
shell: bash
run: |
set -e
TAG="${{ steps.ver.outputs.plain }}"
echo "Tag version: $TAG"
ls dist
# Check that at least one artifact embeds the same version
if ! ls dist/*"$TAG"*.whl dist/*"$TAG"*.tar.gz >/dev/null 2>&1; then
echo "ERROR: Built artifact version does not match tag $TAG"
exit 1
fi
echo "Artifact version matches tag."
- name: D4) Validate built artifacts
# WHY: Twine checks package metadata before publishing.
# Install it only here so it is not required for normal local development.
run: uv tool run twine check dist/*
- name: D5) List dist artifacts
run: ls -lah dist
- name: D6) Create GitHub Release and upload artifacts
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }} # e.g., vx.y.z
name: ${{ github.ref_name }}
generate_release_notes: true
files: |
dist/*.whl
dist/*.tar.gz
draft: false
prerelease: false
make_latest: true
- name: D7) Publish to PyPI (Trusted Publishing)
uses: pypa/gh-action-pypi-publish@release/v1