π ci: PyPI publishing via OIDC trusted publishing β fixed uv publish command, GH release in-pipeline, removed dead publish.yml
swadhinbiswas committed 2 months ago
bf007b1
1 parent 0598cf5
commit bf007b1
3 files changed
+44 -109
Showing 3 changed files+44-109
βΌ.github/workflows/publish.yml
+0-98
| @@ -1,98 +0,0 @@ | ||
1 | -name: Publish to PyPI | |
2 | - | |
3 | -on: | |
4 | - release: | |
5 | - types: [published] | |
6 | - workflow_dispatch: | |
7 | - inputs: | |
8 | - version: | |
9 | - description: 'Version to publish (e.g., 2.0.8)' | |
10 | - required: true | |
11 | - | |
12 | -jobs: | |
13 | - build: | |
14 | - name: Build Wheel | |
15 | - runs-on: ubuntu-latest | |
16 | - steps: | |
17 | - - uses: actions/checkout@v4 | |
18 | - | |
19 | - - name: Install Rust toolchain | |
20 | - uses: dtolnay/rust-toolchain@stable | |
21 | - | |
22 | - - name: Install Python (for PyO3) | |
23 | - uses: actions/setup-python@v5 | |
24 | - with: | |
25 | - python-version: "3.12" | |
26 | - | |
27 | - - name: Cache cargo registry | |
28 | - uses: actions/cache@v4 | |
29 | - with: | |
30 | - path: | | |
31 | - ~/.cargo/registry | |
32 | - ~/.cargo/git | |
33 | - target | |
34 | - key: ${{ runner.os }}-publish-${{ hashFiles('**/Cargo.lock') }} | |
35 | - restore-keys: | | |
36 | - ${{ runner.os }}-publish- | |
37 | - | |
38 | - - name: Install maturin | |
39 | - run: pip install maturin | |
40 | - | |
41 | - - name: Build wheel | |
42 | - run: maturin build --release -m crates/justapi-py/Cargo.toml -o wheels/ | |
43 | - | |
44 | - - name: Verify wheel | |
45 | - run: | | |
46 | - pip install wheels/*.whl --break-system-packages | |
47 | - python -c "import justapi; print(f'JustAPI installed successfully')" | |
48 | - | |
49 | - - name: Upload wheel artifact | |
50 | - uses: actions/upload-artifact@v4 | |
51 | - with: | |
52 | - name: wheels | |
53 | - path: wheels/*.whl | |
54 | - | |
55 | - publish-pypi: | |
56 | - name: Publish to PyPI | |
57 | - runs-on: ubuntu-latest | |
58 | - needs: [build] | |
59 | - environment: pypi | |
60 | - permissions: | |
61 | - id-token: write | |
62 | - # PyPI upload is owned by wheels.yml (7-platform matrix on tag push). | |
63 | - # This job only builds + verifies; the release assets come from wheels.yml. | |
64 | - if: false | |
65 | - steps: | |
66 | - - name: Download wheel artifact | |
67 | - uses: actions/download-artifact@v4 | |
68 | - with: | |
69 | - name: wheels | |
70 | - path: wheels/ | |
71 | - | |
72 | - - name: Publish to PyPI | |
73 | - uses: pypa/gh-action-pypi-publish@release/v1 | |
74 | - with: | |
75 | - packages-dir: wheels/ | |
76 | - | |
77 | - create-github-release: | |
78 | - name: Create GitHub Release | |
79 | - runs-on: ubuntu-latest | |
80 | - # PyPI upload is owned by wheels.yml (7-platform matrix). This job only | |
81 | - # builds + verifies the wheel, then creates the GitHub Release with it. | |
82 | - needs: [build] | |
83 | - permissions: | |
84 | - contents: write | |
85 | - steps: | |
86 | - - uses: actions/checkout@v4 | |
87 | - | |
88 | - - name: Download wheel artifact | |
89 | - uses: actions/download-artifact@v4 | |
90 | - with: | |
91 | - name: wheels | |
92 | - path: wheels/ | |
93 | - | |
94 | - - name: Create GitHub Release | |
95 | - uses: softprops/action-gh-release@v2 | |
96 | - with: | |
97 | - files: wheels/*.whl | |
98 | - generate_release_notes: true | |
99 | 0 | |
βΌ.github/workflows/wheels.yml
+34-4
| @@ -6,6 +6,7 @@ on: | ||
6 | 6 | tags: [ 'v*' ] |
7 | 7 | pull_request: |
8 | 8 | branches: [ main, master ] |
9 | + workflow_dispatch: | |
9 | 10 | |
10 | 11 | permissions: |
11 | 12 | contents: read |
| @@ -95,8 +96,9 @@ jobs: | ||
95 | 96 | - name: Install wheel & test |
96 | 97 | shell: bash |
97 | 98 | run: | |
99 | + uv venv | |
98 | 100 | uv pip install dist/*.whl pytest |
99 | - python -m pytest crates/justapi-py/tests/ -v --tb=short | |
101 | + uv run python -m pytest crates/justapi-py/tests/ -v --tb=short | |
100 | 102 | - name: Upload Wheels |
101 | 103 | uses: actions/upload-artifact@v4 |
102 | 104 | with: |
| @@ -104,13 +106,18 @@ jobs: | ||
104 | 106 | path: dist/*.whl |
105 | 107 | |
106 | 108 | publish: |
107 | - name: Publish to PyPI | |
109 | + name: Publish to PyPI + GitHub Release | |
108 | 110 | runs-on: ubuntu-latest |
109 | 111 | needs: build-wheels |
110 | 112 | if: startsWith(github.ref, 'refs/tags/v') |
113 | + # OIDC trusted publishing β NO token needed. Requires the PyPI project's | |
114 | + # trusted publisher to be configured once at pypi.org (see setup note at | |
115 | + # the bottom of this file). The `pypi` environment is auto-created by | |
116 | + # GitHub on first run. | |
111 | 117 | environment: pypi |
112 | 118 | permissions: |
113 | 119 | id-token: write |
120 | + contents: write | |
114 | 121 | steps: |
115 | 122 | - uses: actions/checkout@v4 |
116 | 123 | - uses: astral-sh/setup-uv@v5 |
| @@ -121,5 +128,28 @@ jobs: | ||
121 | 128 | pattern: wheels-* |
122 | 129 | merge-multiple: true |
123 | 130 | path: dist |
124 | - - name: Publish | |
125 | - run: uv publish --package-dir crates/justapi-py --trusted-publishing always --verbose | |
131 | + - name: Publish to PyPI (trusted publishing) | |
132 | + # `uv publish` defaults to dist/*.whl; `--trusted-publishing always` | |
133 | + # uses the OIDC token from the `pypi` environment β no API token. | |
134 | + run: uv publish --trusted-publishing always | |
135 | + - name: Create GitHub Release | |
136 | + uses: softprops/action-gh-release@v2 | |
137 | + with: | |
138 | + files: dist/*.whl | |
139 | + generate_release_notes: true | |
140 | + | |
141 | +# --- One-time setup (required once, then publishing is fully automated) --- | |
142 | +# | |
143 | +# 1. At pypi.org β Account β Publishing β "Add a new pending publisher": | |
144 | +# β’ Publisher: GitHub | |
145 | +# β’ Owner: swadhinbiswas | |
146 | +# β’ Repository: JustAPI | |
147 | +# β’ Environment: pypi (must match the job's `environment:`) | |
148 | +# β’ Workflow name: wheels.yml | |
149 | +# (Trusted publishing auto-creates the `justapi` project on first upload.) | |
150 | +# | |
151 | +# 2. Push a tag: `git tag v2.0.8 && git push origin v2.0.8` | |
152 | +# | |
153 | +# That's it β no MATURIN_PYPI_TOKEN, no secrets. The wheels.yml `publish` job | |
154 | +# then builds the 7-platform matrix, uploads to PyPI via OIDC, and creates the | |
155 | +# GitHub Release with the wheels attached. | |
126 | 156 | |
βΌscripts/publish.sh
+10-7
| @@ -1,11 +1,13 @@ | ||
1 | 1 | #!/usr/bin/env bash |
2 | -# scripts/publish.sh β build + verify + publish the justapi PyPI wheels. | |
2 | +# scripts/publish.sh β local build + verify (the RELEASE path is CI). | |
3 | 3 | # |
4 | -# The only missing piece for a real release is the PyPI token | |
5 | -# (MATURIN_PYPI_TOKEN / TWINE_PASSWORD). Everything else β portable | |
6 | -# manylinux + musllinux builds for x86_64 + aarch64 (via maturin --zig), | |
7 | -# twine check, fresh-venv install smoke β is done here so | |
8 | -# `bash scripts/publish.sh` is the single release command. | |
4 | +# PRIMARY RELEASE PATH (no token): push a `v*` tag β .github/workflows/wheels.yml | |
5 | +# builds the 7-platform matrix and publishes to PyPI via OIDC trusted | |
6 | +# publishing (see the setup note at the bottom of wheels.yml). This script is | |
7 | +# the local pre-release verification: portable manylinux + musllinux builds | |
8 | +# (maturin --zig), twine check, fresh-venv install smoke. | |
9 | +# | |
10 | +# Legacy token path (kept for emergencies): MATURIN_PYPI_TOKEN=... bash scripts/publish.sh --upload | |
9 | 11 | # |
10 | 12 | # Prereqs: maturin (with --zig; requires zig on PATH), rustup with the |
11 | 13 | # target stds installed (aarch64-unknown-linux-gnu, aarch64-unknown-linux-musl, |
| @@ -73,5 +75,6 @@ if [[ "$UPLOAD" == "--upload" ]]; then | ||
73 | 75 | echo "[publish] DONE β justapi is on PyPI (4 platforms)" |
74 | 76 | else |
75 | 77 | echo "[publish] build + verify OK. To release:" |
76 | - echo " MATURIN_PYPI_TOKEN=... bash scripts/publish.sh --upload" | |
78 | + echo " (preferred) git tag v2.0.8 && git push origin v2.0.8 # CI publishes via OIDC" | |
79 | + echo " (emergency) MATURIN_PYPI_TOKEN=... bash scripts/publish.sh --upload" | |
77 | 80 | fi |
78 | 81 | |