Skip to content

Commit a69d533

Browse files
Merge pull request #5 from thomasisensee/release-pypi
CI pypi release workflow
2 parents 192a704 + 9e20c4b commit a69d533

1 file changed

Lines changed: 146 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
publish_target:
7+
description: "Choose whether to build only, publish to TestPyPI, or publish to PyPI"
8+
required: true
9+
default: dry-run
10+
type: choice
11+
options:
12+
- dry-run
13+
- testpypi
14+
push:
15+
tags:
16+
- "v*"
17+
18+
jobs:
19+
build:
20+
name: Build distribution artifacts
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v6
28+
29+
- name: Set up Python 3.14
30+
uses: actions/setup-python@v6
31+
with:
32+
python-version: "3.14"
33+
34+
- name: Verify release tag matches package version
35+
if: ${{ github.event_name == 'push' || inputs.publish_target == 'testpypi' }}
36+
run: |
37+
python - <<'PY'
38+
import os
39+
import pathlib
40+
import tomllib
41+
42+
pyproject = pathlib.Path("pyproject.toml")
43+
version = tomllib.loads(pyproject.read_text())["project"]["version"]
44+
ref = os.environ["GITHUB_REF"]
45+
expected_ref = f"refs/tags/v{version}"
46+
47+
if ref != expected_ref:
48+
raise SystemExit(
49+
"Publishing requires running this workflow from the "
50+
f"tag {expected_ref}, but GitHub provided {ref!r}."
51+
)
52+
53+
print(f"Publishing from {ref}, matching project version {version}.")
54+
PY
55+
56+
- name: Install build and test dependencies
57+
run: |
58+
python -m pip install --upgrade pip build twine pytest
59+
60+
- name: Build source and wheel distributions
61+
run: |
62+
python -m build
63+
64+
- name: Check built distributions
65+
run: |
66+
python -m twine check dist/*
67+
68+
- name: Install package from built wheel
69+
run: |
70+
python -m pip install --force-reinstall dist/*.whl
71+
72+
- name: Run Python tests
73+
run: |
74+
python -m pytest
75+
76+
- name: Upload built distributions
77+
uses: actions/upload-artifact@v7
78+
with:
79+
name: python-package-distributions
80+
path: dist/*
81+
if-no-files-found: error
82+
83+
publish-testpypi:
84+
name: Publish to TestPyPI
85+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_target == 'testpypi' }}
86+
needs: build
87+
runs-on: ubuntu-latest
88+
permissions:
89+
id-token: write
90+
environment:
91+
name: testpypi
92+
url: https://test.pypi.org/project/stitchmeta/
93+
94+
steps:
95+
- name: Download built distributions
96+
uses: actions/download-artifact@v8
97+
with:
98+
name: python-package-distributions
99+
path: dist/
100+
101+
- name: Publish distributions to TestPyPI
102+
uses: pypa/gh-action-pypi-publish@release/v1
103+
with:
104+
repository-url: https://test.pypi.org/legacy/
105+
106+
publish-pypi:
107+
name: Publish to PyPI
108+
if: ${{ github.event_name == 'push' }}
109+
needs: build
110+
runs-on: ubuntu-latest
111+
permissions:
112+
id-token: write
113+
environment:
114+
name: pypi
115+
url: https://pypi.org/project/stitchmeta/
116+
117+
steps:
118+
- name: Download built distributions
119+
uses: actions/download-artifact@v8
120+
with:
121+
name: python-package-distributions
122+
path: dist/
123+
124+
- name: Publish distributions to PyPI
125+
uses: pypa/gh-action-pypi-publish@release/v1
126+
127+
github-release:
128+
name: Create GitHub Release
129+
if: ${{ github.event_name == 'push' }}
130+
needs: [build, publish-pypi]
131+
runs-on: ubuntu-latest
132+
permissions:
133+
contents: write
134+
135+
steps:
136+
- name: Download built distributions
137+
uses: actions/download-artifact@v8
138+
with:
139+
name: python-package-distributions
140+
path: dist/
141+
142+
- name: Create GitHub Release
143+
uses: softprops/action-gh-release@v2
144+
with:
145+
generate_release_notes: true
146+
files: dist/*

0 commit comments

Comments
 (0)