66 workflow_dispatch : # Allows manual triggering of the workflow
77
88jobs :
9- publish :
9+ release-build :
1010 runs-on : ubuntu-latest
1111
1212 steps :
@@ -18,62 +18,79 @@ jobs:
1818 - name : Set up Python
1919 uses : actions/setup-python@v5
2020 with :
21- python-version : 3.13
21+ python-version : " 3.13"
2222
23- # Step 3: Install dependencies for building and publishing
24- - name : Install build tools
23+ # Verify version matches the release tag
24+ - name : Verify version
25+ if : github.event_name == 'release'
2526 run : |
26- pip install --upgrade pip
27- pip install build twine
27+ PROJECT_VERSION=$(grep "^version = " pyproject.toml | cut -d'"' -f2)
28+ TAG_VERSION=${GITHUB_REF#refs/tags/}
29+ TAG_VERSION=${TAG_VERSION#v}
30+
31+ if [ "$PROJECT_VERSION" != "$TAG_VERSION" ]; then
32+ echo "Version mismatch: pyproject.toml version ($PROJECT_VERSION) doesn't match release tag ($TAG_VERSION)"
33+ exit 1
34+ fi
2835
29- # Step 4 : Build the package
30- - name : Build the package
36+ # Step 3 : Build the package
37+ - name : Build release distributions
3138 run : |
39+ python -m pip install --upgrade pip
40+ python -m pip install build
3241 python -m build
3342
34- # Step 5 : Verify the built package
43+ # Step 4 : Verify the built package
3544 - name : Verify package
3645 run : |
46+ python -m pip install twine
3747 if [ ! -f "dist/*.whl" ] || [ ! -f "dist/*.tar.gz" ]; then
3848 echo "Expected wheel and source distribution files not found in dist/"
3949 exit 1
4050 fi
4151 python -m twine check dist/*
4252
43- # Step 6: Verify version matches the release tag
44- - name : Verify version
45- if : github.event_name == 'release'
46- run : |
47- # Extract version from pyproject.toml
48- PROJECT_VERSION=$(grep "^version = " pyproject.toml | cut -d'"' -f2)
49- # Remove 'v' prefix from tag if present
50- TAG_VERSION=${GITHUB_REF#refs/tags/}
51- TAG_VERSION=${TAG_VERSION#v}
53+ # Step 5: Upload release artifacts
54+ - name : Upload release artifacts
55+ uses : actions/upload-artifact@v4
56+ with :
57+ name : release-dists
58+ path : dist/
5259
53- if [ "$PROJECT_VERSION" != "$TAG_VERSION" ]; then
54- echo "Version mismatch: pyproject.toml version ($PROJECT_VERSION) doesn't match release tag ($TAG_VERSION)"
55- exit 1
56- fi
60+ pypi-publish :
61+ runs-on : ubuntu-latest
62+ needs : [release-build]
63+ environment : pypi
64+ permissions :
65+ id-token : write # Required for PyPI trusted publishing
5766
58- # Step 7: Publish to PyPI
59- - name : Publish to PyPI
60- env :
61- TWINE_USERNAME : __token__
62- TWINE_PASSWORD : ${{ secrets.PYPI_TOKEN }}
63- run : |
64- python -m twine upload --skip-existing dist/*
67+ steps :
68+ # Step 1: Retrieve release distributions
69+ - name : Retrieve release distributions
70+ uses : actions/download-artifact@v4
71+ with :
72+ name : release-dists
73+ path : dist/
74+
75+ # Step 2: Publish to PyPI using OIDC
76+ - name : Publish package distributions to PyPI
77+ uses : pypa/gh-action-pypi-publish@release/v1
78+ with :
79+ verbose : true
80+ print-hash : true
6581
66- # Step 8 : Verify package is available on PyPI
82+ # Step 3 : Verify package is available on PyPI
6783 - name : Verify PyPI upload
6884 run : |
6985 # Wait a bit for PyPI to process the upload
7086 sleep 30
7187
72- # Extract package name from pyproject.toml
73- PACKAGE_NAME=$(grep "^name = " pyproject.toml | cut -d'"' -f2)
88+ # Extract package name from the wheel file (assuming it exists)
89+ WHEEL_FILE=$(ls dist/*.whl | head -n 1)
90+ PACKAGE_NAME=$(basename "$WHEEL_FILE" | cut -d'-' -f1)
91+ PACKAGE_VERSION=$(basename "$WHEEL_FILE" | cut -d'-' -f2)
7492
75- # Check if package exists on PyPI
76- if ! pip install $PACKAGE_NAME==`python setup.py --version` --no-deps --dry-run; then
93+ if ! pip install $PACKAGE_NAME==$PACKAGE_VERSION --no-deps --dry-run; then
7794 echo "Failed to verify package on PyPI"
7895 exit 1
7996 fi
0 commit comments