diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e6ee2f2..df2539c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,9 +3,7 @@ name: Release on: push: tags: ["v*"] - -permissions: - contents: write # create the GitHub release (the sole distribution channel) + workflow_dispatch: # manual (re)publish — e.g. push an already-tagged version to PyPI jobs: build: @@ -31,7 +29,12 @@ jobs: github-release: needs: build + # Only when a tag was pushed — a manual workflow_dispatch run publishes to + # PyPI without recreating the GitHub release for an existing tag. + if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest + permissions: + contents: write # create the GitHub release steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 @@ -43,3 +46,17 @@ jobs: with: files: dist/* generate_release_notes: true + + pypi-publish: + needs: build + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write # OIDC for PyPI Trusted Publishing — no token stored anywhere + steps: + - uses: actions/download-artifact@v4 + with: + name: dist + path: dist + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/docs/RELEASE_CHECKLIST.md b/docs/RELEASE_CHECKLIST.md index fc35e4d..d6c0856 100644 --- a/docs/RELEASE_CHECKLIST.md +++ b/docs/RELEASE_CHECKLIST.md @@ -1,9 +1,11 @@ # Release Checklist A repeatable, copy-pasteable checklist for cutting a `codebase-index` release. -Distribution is **GitHub-only** today (no PyPI publish yet — see "Future -hardening"). Tagging `v*` triggers `.github/workflows/release.yml`, which builds, -`twine check`s, runs the clean-machine smoke, and publishes a GitHub release. +Tagging `v*` triggers `.github/workflows/release.yml`, which builds, +`twine check`s, runs the clean-machine smoke, publishes a **GitHub release**, and +publishes to **PyPI** via Trusted Publishing (OIDC — no stored token). A manual +`workflow_dispatch` run publishes the current `main` build to PyPI without +recreating a GitHub release (used to publish an already-tagged version). Work top to bottom. Do not tag until every required box is checked.