Phase 6f: add publish-python to release.yml (PyPI via OIDC) - #25
Merged
Merged
Conversation
Three new jobs wired into the release pipeline alongside the
existing publish-crate / publish-ffi / publish-desktop chain:
- build-python-wheels (matrix, 4 cells)
- build-python-sdist (single)
- publish-python (aggregate + upload + GitHub Release)
**Why three jobs instead of one matrix with inline upload:**
PyPI expects wheels as a single batch — if each matrix cell
published its own wheel independently, a mid-matrix failure
would leave PyPI with a partial wave of a release, which is
worse than the whole thing failing cleanly. The build/publish
split aggregates every wheel + the sdist into one `dist/`
directory, then uploads atomically via
`pypa/gh-action-pypi-publish`.
**Wheel matrix** mirrors publish-ffi + publish-desktop:
ubuntu-latest → linux x86_64 (manylinux2014)
ubuntu-24.04-arm → linux aarch64 (manylinux2014)
macos-latest → macOS aarch64 (Apple Silicon)
windows-latest → windows x86_64
abi3-py38 means one wheel per platform works on every CPython
≥ 3.8 — no per-Python-version axis. An sdist is built alongside
for platforms not covered by the wheel matrix (FreeBSD,
alpine aarch64, etc.); `pip install` falls back to a source
build via the user's local Rust toolchain.
**Authentication via PyPI trusted publishing** (OIDC). Zero
long-lived tokens. The publish-python job has `permissions:
id-token: write` and lives in the `release` GitHub environment
(required-reviewer gate inherited from publish-crate). PyPI-side
config is a one-time web-UI registration documented in
docs/release-secrets.md.
**Wiring:**
- tag-all → pushes sqlrite-py-v<V>
- finalize → needs publish-python
- umbrella release body → includes 🐍 Python link pointing
to the per-product release + PyPI page
Verified locally: `cargo check -p sqlrite-python` clean,
release.yml parses as valid YAML, pyproject.toml already has
name = "sqlrite" (available on PyPI per pypi.org API, no
rename dance like crates.io needed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds three new jobs to
release.ymlthat build + publishsqlriteto PyPI on every release, authenticating via OIDC trusted publishing (no API token).build-python-wheelsbuild-python-sdistpublish-pythonsqlrite-py-v<V>GitHub ReleaseWhy three jobs, not one matrix with inline upload
If each matrix cell published its own wheel directly to PyPI, a mid-matrix failure would leave PyPI with a partial wave (3 of 4 platforms). The build/publish split lets us fail cleanly — nothing hits PyPI until every platform's wheel is in hand.
Matrix choices
Mirrors
publish-ffi+publish-desktopso there's one consistent OS/arch pattern across all publish jobs:manylinux: autoruns the build inside a manylinux2014 container, so the wheel's glibc is baked old enough to run on any distro shipped since ~2014.abi3-py38 means one wheel per platform covers every CPython ≥ 3.8 — no per-Python-version matrix axis. The sdist catches anyone on uncommon platforms (FreeBSD, alpine aarch64, etc.) —
pip install sqlritefalls back to source build using their local Rust toolchain.Authentication
OIDC trusted publishing via
pypa/gh-action-pypi-publish@release/v1. Thepublish-pythonjob haspermissions: id-token: writeand lives in thereleaseGitHub environment (same required-reviewer gate aspublish-crate). PyPI-side config is one-time web-UI registration ofjoaoh82/rust_sqlite→release.yml→releaseenvironment as a trusted publisher for thesqlriteproject (documented indocs/release-secrets.md).Wiring
tag-all→ now pushessqlrite-py-v<V>finalize.needs→ extended withpublish-pythonName availability
Unlike
sqlriteon crates.io (taken by an unrelated project, forcing thesqlrite-enginerename in PR #17), the namesqlriteis available on PyPI — verified viacurl -o /dev/null -w "%{http_code}" https://pypi.org/pypi/sqlrite/jsonreturning 404.pyproject.tomlalready hasname = "sqlrite", no rename needed.Test plan
cargo check -p sqlrite-python— cleanpython3 -c "import yaml; yaml.safe_load(open('.github/workflows/release.yml'))"— YAML parses/pypi/sqlrite/json)sqlriteproject name, configure trusted publisher pointing at this repo /release.yml/ environmentrelease. Documented indocs/release-secrets.md§2.release-pr.ymlat0.1.4→ review → merge → approvereleaseenv → verifysqlrite 0.1.4on PyPI +sqlrite-py-v0.1.4GitHub Release.Not in scope (Phase 6g–6i follow-ups)
Node.js (npm), WASM (npm), Go (git tag + FFI tarball attachment). Each lands as its own PR.
🤖 Generated with Claude Code