Skip to content

Commit 35716c3

Browse files
committed
Prep v0.9.13
1 parent 0cd87cd commit 35716c3

1 file changed

Lines changed: 131 additions & 9 deletions

File tree

.github/workflows/release.yml

Lines changed: 131 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,145 @@
1-
# .github/workflows/release-python.yml
1+
# .github/workflows/release.yml
22
name: Release (PyPI + versioned docs)
3+
34
# Designed to run only on version tags (e.g., vx.y.z).
45
# Final step before distribution.
56
# It builds distribution files, runs tests, prepares release, and publishes.
67
# IMPORTANT: The PyPI project must enable Trusted Publishers and recognize this repository.
78

9+
# CI PHASES A-B-C-D:
10+
# - Assemble: Install dependencies, verify environment setup
11+
# - Baseline: Core validation (types exist, lint passes, tests pass)
12+
# - Coverage: Generate coverage / testing reports
13+
# - Deploy: Build package and docs (sanity checks for release readiness)
14+
815
on:
916
push:
1017
tags:
11-
- "v*.*.*" # trigger only on version tags like vx.y.z
18+
- "v*.*.*"
1219

1320
permissions:
14-
contents: write # create the GitHub Release
15-
id-token: write # PyPI Trusted Publishing (OIDC)
21+
contents: write # create the GitHub Release
22+
id-token: write # PyPI Trusted Publishing (OIDC)
1623

17-
concurrency:
18-
group: release-${{ github.ref }}
19-
cancel-in-progress: true
24+
env:
25+
PYTHONUNBUFFERED: "1" # real-time logging
26+
PYTHONIOENCODING: "utf-8"
27+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2028

2129
jobs:
22-
release:
23-
uses: civic-interconnect/.github/.github/workflows/release-python.yml@main
30+
build-and-release:
31+
runs-on: ubuntu-latest
32+
environment: pypi
33+
timeout-minutes: 30
34+
35+
steps:
36+
# ------------------- ASSEMBLE -------------------
37+
38+
- name: A1) Checkout (with tag history)
39+
uses: actions/checkout@v5
40+
with:
41+
fetch-depth: 0 # Full history for tags
42+
43+
- name: A2) Install uv (with caching)
44+
uses: astral-sh/setup-uv@v7
45+
with:
46+
enable-cache: true
47+
48+
- name: A3) Pin Python version for consistency
49+
run: uv python pin 3.12
50+
51+
- name: A4) Display version information
52+
run: |
53+
python --version
54+
uv --version
55+
uv pip list | head -n 50
56+
57+
- name: A5) Sync to install dependencies
58+
run: |
59+
uv sync --extra dev --extra docs --upgrade
60+
61+
# ------------------- BASELINE / TESTS -------------------
62+
63+
- name: B1) Validate pyproject
64+
run: uvx validate-pyproject
65+
66+
- name: B2) Ruff lint (check only)
67+
run: uvx ruff check .
68+
69+
- name: B3) Pyright (type check)
70+
run: uv run pyright
71+
72+
- name: B4) Deptry (dependency check)
73+
run: uvx deptry .
74+
75+
# ------------------- COVERAGE (TESTING) -------------------
76+
77+
- name: C1) Run tests (pytest; coverage per pytest.ini)
78+
run: uv run pytest -q
79+
80+
# ------------ DEPLOY (BUILD, RELEASE, DOCS) -------------------
81+
82+
- name: D1) Extract plain version from tag (no leading 'v')
83+
id: ver
84+
shell: bash
85+
run: echo "plain=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
86+
87+
- name: D2) Build sdist + wheel
88+
env:
89+
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ steps.ver.outputs.plain }}
90+
run: uv build
91+
92+
- name: D3) Ensure built artifact version matches tag
93+
shell: bash
94+
run: |
95+
set -e
96+
TAG="${{ steps.ver.outputs.plain }}"
97+
echo "Tag version: $TAG"
98+
ls dist
99+
# Check that at least one artifact embeds the same version
100+
if ! ls dist/*"$TAG"*.whl dist/*"$TAG"*.tar.gz >/dev/null 2>&1; then
101+
echo "ERROR: Built artifact version does not match tag $TAG"
102+
exit 1
103+
fi
104+
echo "Artifact version matches tag."
105+
106+
- name: D4) Validate built artifacts
107+
run: uv run twine check dist/*
108+
109+
- name: D5) List dist artifacts
110+
run: ls -lah dist
111+
112+
- name: D6) Create GitHub Release and upload artifacts
113+
uses: softprops/action-gh-release@v2
114+
with:
115+
tag_name: ${{ github.ref_name }} # e.g., vx.y.z
116+
name: ${{ github.ref_name }}
117+
generate_release_notes: true
118+
files: |
119+
dist/*.whl
120+
dist/*.tar.gz
121+
draft: false
122+
prerelease: false
123+
make_latest: true
124+
125+
- name: D7) Publish to PyPI
126+
uses: pypa/gh-action-pypi-publish@release/v1
127+
128+
- name: D8) Ensure 'latest' is not a version (self-heal)
129+
if: hashFiles('mkdocs.yml', 'mkdocs.yaml') != ''
130+
run: uv run mike delete latest --push || true
131+
132+
- name: D9) Deploy docs with Mike for this version and set latest
133+
if: hashFiles('mkdocs.yml', 'mkdocs.yaml') != ''
134+
run: |
135+
set -e
136+
git config user.name "github-actions[bot]"
137+
git config user.email "github-actions[bot]@users.noreply.github.com"
138+
VERSION="${{ steps.ver.outputs.plain }}"
139+
echo "Deploying docs for version: $VERSION"
140+
uv run mike deploy --push --update-aliases "$VERSION" latest
141+
uv run mike set-default --push latest
142+
143+
- name: D10) Show mike versions (after)
144+
if: hashFiles('mkdocs.yml', 'mkdocs.yaml') != ''
145+
run: uv run mike list

0 commit comments

Comments
 (0)