6
6
workflow_dispatch : # Allows manual triggering of the workflow
7
7
8
8
jobs :
9
- publish :
9
+ release-build :
10
10
runs-on : ubuntu-latest
11
11
12
12
steps :
@@ -18,62 +18,79 @@ jobs:
18
18
- name : Set up Python
19
19
uses : actions/setup-python@v5
20
20
with :
21
- python-version : 3.13
21
+ python-version : " 3.13"
22
22
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'
25
26
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
28
35
29
- # Step 4 : Build the package
30
- - name : Build the package
36
+ # Step 3 : Build the package
37
+ - name : Build release distributions
31
38
run : |
39
+ python -m pip install --upgrade pip
40
+ python -m pip install build
32
41
python -m build
33
42
34
- # Step 5 : Verify the built package
43
+ # Step 4 : Verify the built package
35
44
- name : Verify package
36
45
run : |
46
+ python -m pip install twine
37
47
if [ ! -f "dist/*.whl" ] || [ ! -f "dist/*.tar.gz" ]; then
38
48
echo "Expected wheel and source distribution files not found in dist/"
39
49
exit 1
40
50
fi
41
51
python -m twine check dist/*
42
52
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/
52
59
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
57
66
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
65
81
66
- # Step 8 : Verify package is available on PyPI
82
+ # Step 3 : Verify package is available on PyPI
67
83
- name : Verify PyPI upload
68
84
run : |
69
85
# Wait a bit for PyPI to process the upload
70
86
sleep 30
71
87
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)
74
92
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
77
94
echo "Failed to verify package on PyPI"
78
95
exit 1
79
96
fi
0 commit comments