-
Notifications
You must be signed in to change notification settings - Fork 2
175 lines (154 loc) · 5.31 KB
/
pypi-release.yml
File metadata and controls
175 lines (154 loc) · 5.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
name: Publish package (TestPyPI -> PyPI)
concurrency:
group: pypi-release-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches:
- release
release:
types: [published]
workflow_dispatch:
inputs:
publish_pypi:
description: "Also publish to production PyPI"
required: true
default: false
type: boolean
jobs:
build-and-test:
name: Build and smoke-test package
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Pixi
uses: prefix-dev/setup-pixi@v0.8.8
with:
pixi-version: v0.44.0
- name: Run CLI help smoke tests
run: |
mkdir -p testing_folder/outputs
pixi run -e dev pytest -q src/tests/test_cli_help_smoke.py
- name: Verify tag matches package version
if: github.event_name == 'release'
run: |
python - <<'PY'
import os
import re
import tomllib
from pathlib import Path
pyproject = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
version_file = pyproject["tool"]["hatch"]["version"]["path"]
version_text = Path(version_file).read_text(encoding="utf-8")
match = re.search(r"__version__\s*=\s*['\"]([^'\"]+)['\"]", version_text)
if not match:
raise SystemExit(f"Could not parse __version__ from {version_file}")
package_version = match.group(1)
release_tag = os.environ["GITHUB_REF_NAME"]
normalized_tag = release_tag[1:] if release_tag.startswith("v") else release_tag
if normalized_tag != package_version:
raise SystemExit(
f"Release tag ({release_tag}) does not match package version ({package_version})"
)
print(f"Version check passed: tag={release_tag}, package={package_version}")
PY
- name: Build wheel + sdist
run: |
rm -rf dist build
pixi run -e dev python -m pip install --upgrade build
pixi run -e dev python -m build --sdist --wheel --outdir dist
- name: Twine metadata check
run: pixi run -e dev twine check dist/*
- name: Upload dist artifacts
uses: actions/upload-artifact@v4
with:
name: python-dist
path: dist/*
if-no-files-found: error
publish-testpypi:
name: Publish to TestPyPI
needs: build-and-test
runs-on: ubuntu-latest
permissions:
id-token: write
environment:
name: testpypi
url: https://test.pypi.org/p/rolypoly-tk
steps:
- name: Download dist artifacts
uses: actions/download-artifact@v4
with:
name: python-dist
path: dist
- name: Publish package to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
smoke-install-testpypi:
name: Smoke-test install from TestPyPI
needs: publish-testpypi
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download dist artifacts
uses: actions/download-artifact@v4
with:
name: python-dist
path: dist
- name: Determine built version
id: version
run: |
python - <<'PY'
import os
from pathlib import Path
wheel = next(Path('dist').glob('*.whl')).name
version = wheel.split('-')[1]
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fh:
fh.write(f"version={version}\n")
print(f"Built version: {version}")
PY
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install from TestPyPI (retry for index lag)
env:
PKG_VERSION: ${{ steps.version.outputs.version }}
run: |
python -m pip install --upgrade pip
for attempt in 1 2 3 4 5 ; do
echo "Attempt ${attempt}: installing rolypoly_tk==${PKG_VERSION} from TestPyPI"
if python -m pip install --no-deps --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple "rolypoly_tk==${PKG_VERSION}"; then
break
fi
if [ "${attempt}" -eq 5 ]; then
echo "Failed to install package from TestPyPI after retries"
exit 1
fi
sleep 20
done
- name: Verify import + CLI
run: |
python -m pip install --index-url https://pypi.org/simple rich-click polars
python -c "import rolypoly; print(rolypoly.__version__)"
rolypoly --help >/dev/null
publish-pypi:
name: Publish to PyPI
needs: smoke-install-testpypi
if: github.event_name == 'release' || github.ref == 'refs/heads/release' || (github.event_name == 'workflow_dispatch' && inputs.publish_pypi)
runs-on: ubuntu-latest
permissions:
id-token: write
environment:
name: pypi
url: https://pypi.org/p/rolypoly-tk
steps:
- name: Download dist artifacts
uses: actions/download-artifact@v4
with:
name: python-dist
path: dist
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1