Skip to content

ci(release): publish to PyPI, which README has been promising all along - #81

Merged
rmichaelthomas merged 1 commit into
mainfrom
ci/publish-to-pypi-on-tag
Sep 12, 2026
Merged

rmichaelthomas merged 1 commit into
mainfrom
ci/publish-to-pypi-on-tag

Conversation

@rmichaelthomas

Copy link
Copy Markdown
Owner

README.md line 54 is pip install liminate, and both liminate-receipts and liminate-contract-inheritance depend on the PyPI distribution. PyPI is a real release channel for this project and it was never in this workflow — the workflow builds signed binaries and attaches them to a GitHub Release, and that is all it has ever done.

Through 0.18.1 someone uploaded by hand, so the binaries and the package could drift apart with nothing to notice. 0.18.2 is where it showed: three signed binaries shipped while pip install liminate stayed on 0.18.1 — and on four missing behaviour fixes, one of which stops includes from validating clean and silently emptying a list.

What this adds

A publish-pypi job on the same tag trigger, using trusted publishing (OIDC) — matching what @liminate/ts-validator moved to this week. PyPI mints a one-time credential for this workflow; nothing is stored, nothing expires, nothing to rotate in 90 days.

No GitHub environment gate. It is optional on PyPI's side, and every field that has to match between this file and the PyPI form is another way a release fails at the last step.

The job verifies the tag against pyproject.toml before building, same guard the validator's release has.

Also: [build-system] declared

There was no such table through 0.18.1. Every build worked because pip supplies setuptools when a project names no backend, and setuptools auto-discovers a src/ layout. Both are conveniences, not guarantees, and a release build should not rest on either.

Verified locally: python -m build produces liminate-0.18.2.tar.gz and liminate-0.18.2-py3-none-any.whl, with 21 modules and the packs/ data present in the wheel.

⚠️ One thing on PyPI first

The trusted publisher must exist before this workflow runs. Configuring it does not disable manual uploads, so doing it first is safe.

pypi.org → liminate → Manage → Publishing → Add a new GitHub publisher:

Field Value
Owner rmichaelthomas
Repository name liminate
Workflow name release.yml
Environment name (leave empty)

Then re-push the v0.18.2 tag to run the workflow with this job in it. Nothing was published to PyPI under 0.18.2, so no version number is burned.

🤖 Generated with Claude Code

https://claude.ai/code/session_01E6qcDj1e1dEYvc8jLnpGZy

README.md's install line is `pip install liminate`, and both
liminate-receipts and liminate-contract-inheritance depend on the PyPI
distribution. PyPI is a real release channel for this project and it was
never in this workflow — the workflow builds signed binaries and attaches
them to a GitHub Release, and that is all it has ever done.

Through 0.18.1 someone uploaded to PyPI by hand, so the binaries and the
package could drift apart with nothing to notice. 0.18.2 is where that
showed: it shipped three signed binaries while `pip install liminate` stayed
on 0.18.1 and on four missing behaviour fixes, one of which stops `includes`
from silently emptying a list.

Authentication is trusted publishing (OIDC), matching what the TypeScript
validator moved to this week: PyPI mints a one-time credential for this
workflow, nothing is stored, nothing expires. No GitHub environment gate —
the fewer fields that have to match between here and the PyPI form, the
fewer ways a release fails at the last step.

Also declares [build-system] and package discovery. There was no such table
through 0.18.1: every build worked because pip supplies setuptools when a
project names no backend and setuptools auto-discovers a src/ layout. Both
are conveniences rather than guarantees, and a release build should not rest
on either. Verified locally — sdist and wheel build clean, 21 modules and the
packs data present in the wheel.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6qcDj1e1dEYvc8jLnpGZy
@rmichaelthomas
rmichaelthomas merged commit ba4e04c into main Sep 12, 2026
3 checks passed
@rmichaelthomas
rmichaelthomas deleted the ci/publish-to-pypi-on-tag branch September 12, 2026 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant