Skip to content

Tag-driven PyPI release workflow (OIDC, no tokens) - #31

Open
joshlin111 wants to merge 1 commit into
mainfrom
feat/pypi-release-workflow
Open

Tag-driven PyPI release workflow (OIDC, no tokens)#31
joshlin111 wants to merge 1 commit into
mainfrom
feat/pypi-release-workflow

Conversation

@joshlin111

Copy link
Copy Markdown
Collaborator

Summary

Adds .github/workflows/release.yml — a 4-job pipeline triggered by v* tag pushes:

  1. Offline tests (gate) — reruns make test on the tagged commit so a stale or off-main tag can't ship a broken release.
  2. Build sdist + wheel — fails fast if the tag name doesn't match pyproject.toml's version (catches "tagged v3.4.1 but forgot to bump").
  3. Publish to PyPI — uses pypa/gh-action-pypi-publish with OIDC trusted publishing. No long-lived PyPI token in repo secrets. Bound to a pypi GitHub Environment so a Required reviewer can gate every release.
  4. Create GitHub Release — attaches the built sdist + wheel and auto-generates release notes from the commits since the previous tag.

One-time setup required before the first release tag works

This PR is safe to merge as-is — the workflow does nothing until a v* tag is pushed. But the first tag will fail unless these are configured:

On PyPI

Go to https://pypi.org/manage/project/apexomni/settings/publishing/Add a new trusted publisher:

Field Value
Owner ApeX-Protocol
Repository name apexpro-openapi
Workflow filename release.yml
Environment name pypi

(If the PyPI project page isn't accessible because no maintainer here owns it on PyPI, that's a blocker — sort the ownership first.)

On GitHub

Settings → Environments → New environment named exactly pypi:

  • (Recommended) Required reviewers — add one or two people who must approve each release before the PyPI upload step proceeds.
  • (Recommended) Deployment branches and tags — restrict to main so a tag pushed from a feature branch can't trigger a release.

How to cut a release after setup is done

# 1. Bump version in pyproject.toml on a PR, merge to main.
# 2. From the merged main commit:
git checkout main && git pull
git tag v3.4.1
git push origin v3.4.1

The PyPI URL, the GitHub Release page, and a cached wheel artifact all appear within ~5 minutes.

Test plan

  • Tag/version match check verified locally with both passing (v3.4.0 vs version = \"3.4.0\") and failing (v9.9.9) cases.
  • make test green via pre-push hook.
  • CI pass on this PR (workflow only parses on PRs — actual end-to-end will be verified by the first real tag push after PyPI + Environment are configured).

- .github/workflows/release.yml fires on `v*` tags and runs a 4-job
  pipeline: offline test gate → build sdist+wheel → publish to PyPI →
  attach artefacts to a GitHub Release.
- PyPI upload uses OIDC trusted publishing (pypa/gh-action-pypi-publish)
  bound to a `pypi` GitHub Environment — no long-lived token in repo
  secrets. The Environment can carry Required reviewers, so each release
  gates on a human approval click before the upload step runs.
- Build job rejects any tag whose name doesn't match the version in
  pyproject.toml, so accidental "tagged v3.4.1 but forgot to bump" is
  caught before anything ships.
- README documents the release flow and the one-time PyPI Trusted
  Publisher + GitHub Environment setup the workflow expects.
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