Skip to content

Commit da1aee3

Browse files
committed
python: abi3 wheels, CI gate on publish, musllinux, action pins
P1: enable pyo3/abi3-py39 in the python feature. One wheel per platform/arch now covers CPython 3.9-3.13+ instead of being tied to the host Python ABI; published wheel name becomes pyvicinity-X.Y.Z-cp39-abi3-{plat}. Caveat: abi3 is incompatible with free-threaded CPython (3.13t+); revisit if/when free-threaded support is requested. Verified locally: maturin develop and maturin build both produce cp39-abi3 wheels; the existing 168 Rust unit tests + 23 Python tests + stubtest all pass. P2: gate publish-pypi on CI green for the same SHA. Previously the only gate was a text-input "confirm=publish" check; the workflow could ship wheels for a SHA whose CI was red or pending. Add a guard step that queries the GitHub API for the most recent ci.yml run on $GITHUB_SHA and aborts unless conclusion == success. P3: add musllinux x86_64 + aarch64 to the wheel matrix. Alpine and other musl-based distros previously had no wheel and would fall back to building from sdist. P4: pin all GitHub Actions to specific minor versions instead of moving major tags. Tags like @v1 / @release/v1 are mutable refs and have been abused for supply-chain attacks; specific versions are reproducible and auditable. checkout v6.0.2, setup-python v6.2.0 (was v5), upload-artifact v7.0.1 (was v4), download-artifact v8.0.1 (was v4), maturin-action v1.51.0, gh-action-pypi-publish v1.14.0 (was release/v1). P5: expand [project.urls] in pyproject.toml with Documentation, Issues, and Changelog so PyPI's project page and `pip show` link to all three. All five items recommended by /scrutinize 2026-04-28; user greenlit "proceed on all fronts".
1 parent ca16daf commit da1aee3

3 files changed

Lines changed: 58 additions & 19 deletions

File tree

.github/workflows/publish-pypi.yml

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,67 +16,98 @@ jobs:
1616
guard:
1717
runs-on: ubuntu-latest
1818
steps:
19-
- name: Guard
19+
- name: Confirm input
2020
run: |
2121
if [ "${{ inputs.confirm }}" != "publish" ]; then
2222
echo "Refusing to publish: set workflow input confirm=publish"
2323
exit 1
2424
fi
25+
- name: Verify CI passed for this SHA
26+
env:
27+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28+
run: |
29+
set -euo pipefail
30+
conclusion=$(gh run list \
31+
--repo "$GITHUB_REPOSITORY" \
32+
--workflow=ci.yml \
33+
--commit="$GITHUB_SHA" \
34+
--json conclusion \
35+
--jq '.[0].conclusion // "missing"')
36+
echo "CI conclusion for $GITHUB_SHA: $conclusion"
37+
if [ "$conclusion" != "success" ]; then
38+
echo "::error::CI for $GITHUB_SHA is '$conclusion', not 'success'. Aborting publish."
39+
exit 1
40+
fi
2541
42+
# Wheels are abi3 (cp39-abi3) -- one wheel per platform/arch covers all
43+
# CPython 3.9+ versions. Free-threaded Python is not supported by abi3.
2644
build-wheels:
2745
needs: guard
2846
strategy:
2947
matrix:
3048
include:
3149
- os: ubuntu-latest
3250
target: x86_64-unknown-linux-gnu
33-
platform: manylinux
51+
manylinux: "2_28"
52+
artifact-suffix: manylinux-x86_64
53+
- os: ubuntu-latest
54+
target: aarch64-unknown-linux-gnu
55+
manylinux: "2_28"
56+
artifact-suffix: manylinux-aarch64
57+
- os: ubuntu-latest
58+
target: x86_64-unknown-linux-gnu
59+
manylinux: "musllinux_1_2"
60+
artifact-suffix: musllinux-x86_64
3461
- os: ubuntu-latest
3562
target: aarch64-unknown-linux-gnu
36-
platform: manylinux
63+
manylinux: "musllinux_1_2"
64+
artifact-suffix: musllinux-aarch64
3765
- os: macos-14
3866
target: aarch64-apple-darwin
39-
platform: macosx
67+
manylinux: "auto"
68+
artifact-suffix: macos-arm64
4069
- os: macos-13
4170
target: x86_64-apple-darwin
42-
platform: macosx
71+
manylinux: "auto"
72+
artifact-suffix: macos-x86_64
4373
- os: windows-latest
4474
target: x86_64-pc-windows-msvc
45-
platform: windows
75+
manylinux: "auto"
76+
artifact-suffix: windows-x86_64
4677
runs-on: ${{ matrix.os }}
4778
steps:
48-
- uses: actions/checkout@v6
49-
- uses: actions/setup-python@v5
79+
- uses: actions/checkout@v6.0.2
80+
- uses: actions/setup-python@v6.2.0
5081
with:
5182
python-version: "3.11"
5283
- name: Build wheels
53-
uses: PyO3/maturin-action@v1
84+
uses: PyO3/maturin-action@v1.51.0
5485
with:
5586
target: ${{ matrix.target }}
5687
args: --release --out dist --features "hnsw,python,parallel"
57-
manylinux: ${{ matrix.platform == 'manylinux' && '2_28' || 'auto' }}
88+
manylinux: ${{ matrix.manylinux }}
5889
- name: Upload wheels
59-
uses: actions/upload-artifact@v4
90+
uses: actions/upload-artifact@v7.0.1
6091
with:
61-
name: wheels-${{ matrix.platform }}-${{ matrix.target }}
92+
name: wheels-${{ matrix.artifact-suffix }}
6293
path: dist/*.whl
6394
if-no-files-found: error
6495

6596
build-sdist:
6697
needs: guard
6798
runs-on: ubuntu-latest
6899
steps:
69-
- uses: actions/checkout@v6
70-
- uses: actions/setup-python@v5
100+
- uses: actions/checkout@v6.0.2
101+
- uses: actions/setup-python@v6.2.0
71102
with:
72103
python-version: "3.11"
73104
- name: Build sdist
74-
uses: PyO3/maturin-action@v1
105+
uses: PyO3/maturin-action@v1.51.0
75106
with:
76107
command: sdist
77108
args: --out dist
78109
- name: Upload sdist
79-
uses: actions/upload-artifact@v4
110+
uses: actions/upload-artifact@v7.0.1
80111
with:
81112
name: sdist
82113
path: dist/*.tar.gz
@@ -88,11 +119,11 @@ jobs:
88119
environment: pypi
89120
steps:
90121
- name: Gather dist artifacts
91-
uses: actions/download-artifact@v4
122+
uses: actions/download-artifact@v8.0.1
92123
with:
93124
path: dist
94125
merge-multiple: true
95126
- name: Publish to PyPI (trusted publishing)
96-
uses: pypa/gh-action-pypi-publish@release/v1
127+
uses: pypa/gh-action-pypi-publish@v1.14.0
97128
with:
98129
packages-dir: dist

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ thiserror = "2.0"
3030
# Note: do NOT enable `pyo3/extension-module` here. It breaks `cargo test --all-features`
3131
# by disabling libpython linking for test binaries on macOS.
3232
# Maturin sets `PYO3_BUILD_EXTENSION_MODULE=1` when building wheels.
33-
pyo3 = { version = "0.27.2", optional = true }
33+
#
34+
# `abi3-py39` builds a stable-ABI wheel that works on CPython 3.9+, so one
35+
# wheel per platform/arch covers every supported Python version. Caveat:
36+
# abi3 wheels are not compatible with free-threaded CPython (3.13t+); revisit
37+
# if/when free-threaded support is requested.
38+
pyo3 = { version = "0.27.2", optional = true, features = ["abi3-py39"] }
3439
numpy = { version = "0.27.0", optional = true }
3540

3641
# SIMD primitives (ecosystem crate)

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ classifiers = [
2121
[project.urls]
2222
Homepage = "https://github.com/arclabs561/vicinity"
2323
Source = "https://github.com/arclabs561/vicinity"
24+
Documentation = "https://docs.rs/vicinity"
25+
Issues = "https://github.com/arclabs561/vicinity/issues"
26+
Changelog = "https://github.com/arclabs561/vicinity/blob/main/CHANGELOG.md"
2427

2528
[project.optional-dependencies]
2629
ann-benchmarks = ["h5py"]

0 commit comments

Comments
 (0)