1- name : Build and Publish to PyPI
1+ name : Build container, build wheel, publish to PyPI
22
33on :
44 push :
5+ branches :
6+ - main
57 tags :
6- - " v*" # only run on version tags like v0.1.0, v1.0.0 etc.
8+ - ' v*' # publishing to PyPI happens only for tags like v0.1.0
9+
10+ # allow pushing to GHCR
11+ permissions :
12+ contents : read
13+ packages : write
714
815jobs :
9- build :
10- name : Build Python 3.9 Wheel
16+ build-container :
17+ name : Build & push container image
1118 runs-on : ubuntu-latest
12-
19+ # image name uses repository and current commit SHA
20+ env :
21+ IMAGE_NAME : ghcr.io/${{ github.repository }}:${{ github.sha }}
22+ outputs :
23+ image : ${{ steps.set-output-img.outputs.image }}
1324 steps :
1425 - name : Checkout repository
1526 uses : actions/checkout@v4
1627 with :
1728 submodules : recursive
1829
19- - name : Set up Python 3.9
20- uses : actions/setup-python@v5
30+ - name : Log in to GHCR
31+ uses : docker/login-action@v2
32+ with :
33+ registry : ghcr.io
34+ username : ${{ github.actor }}
35+ password : ${{ secrets.GITHUB_TOKEN }}
36+
37+ - name : Build and push Docker image
38+ uses : docker/build-push-action@v5
39+ with :
40+ context : .
41+ file : container/Dockerfile
42+ push : true
43+ tags : ${{ env.IMAGE_NAME }}
44+
45+ - name : Expose built image name (job output)
46+ id : set-output-img
47+ run : |
48+ echo "image=${{ env.IMAGE_NAME }}" >> $GITHUB_OUTPUT
49+
50+ build-python-package :
51+ name : Build Python wheel (uses the built image)
52+ runs-on : ubuntu-latest
53+ needs : build-container
54+ # run the job inside the just-built image; authenticate to pull from GHCR
55+ container :
56+ image : ${{ needs.build-container.outputs.image }}
57+ credentials :
58+ username : ${{ github.actor }}
59+ password : ${{ secrets.GITHUB_TOKEN }}
60+ steps :
61+ - name : Checkout repository
62+ uses : actions/checkout@v4
2163 with :
22- python-version : " 3.9"
64+ submodules : recursive
65+
66+ - name : Ensure Python 3.9 (best-effort)
67+ run : |
68+ # if python3.9 is already in the image this is a no-op; otherwise try to install
69+ if command -v python3.9 >/dev/null 2>&1; then
70+ python3.9 -V
71+ elif command -v python3 >/dev/null 2>&1 && python3 -V | grep -q "3.9"; then
72+ python3 -V
73+ else
74+ apt-get update && apt-get install -y python3.9 python3.9-dev python3-pip || true
75+ # try to make python3 point to 3.9 if needed
76+ if [ -f /usr/bin/python3.9 ]; then
77+ update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 || true
78+ fi
79+ fi
2380
24- - name : Install dependencies
81+ - name : Install Python deps
2582 run : |
26- python -m pip install --upgrade pip
27- pip install -r requirements.txt
28- pip install build wheel
83+ python3 -m pip install --upgrade pip
84+ python3 -m pip install -r requirements.txt || true
85+ python3 -m pip install wheel
2986
3087 - name : Build wheel
3188 run : |
32- python setup.py build_ext -j$(nproc) bdist_wheel
33- ls -lh dist/
89+ # parallel compilation as in your GitLab CI
90+ python3 setup.py build_ext -j64 bdist_wheel
91+ ls -lh dist || true
3492
35- - name : Upload artifact
93+ - name : Upload wheel artifact
3694 uses : actions/upload-artifact@v4
3795 with :
3896 name : wheel-dist
3997 path : dist/*.whl
4098
4199 publish :
42100 name : Publish to PyPI
43- needs : build
44101 runs-on : ubuntu-latest
102+ needs : build-python-package
45103 if : startsWith(github.ref, 'refs/tags/')
46-
47104 steps :
48105 - name : Download wheel artifact
49106 uses : actions/download-artifact@v4
@@ -54,14 +111,14 @@ jobs:
54111 - name : Set up Python 3.9
55112 uses : actions/setup-python@v5
56113 with :
57- python-version : " 3.9"
114+ python-version : ' 3.9'
58115
59- - name : Install Twine
116+ - name : Install twine
60117 run : python -m pip install --upgrade pip twine
61118
62119 - name : Publish to PyPI
63120 env :
64121 TWINE_USERNAME : __token__
65122 TWINE_PASSWORD : ${{ secrets.PYPI_API_TOKEN }}
66123 run : |
67- twine upload dist/* --verbose
124+ python -m twine upload dist/* --verbose
0 commit comments