From c712c0edca3788bd4fea308c45034b4a1a07c506 Mon Sep 17 00:00:00 2001 From: Rob Figueiredo Date: Wed, 2 Sep 2026 20:02:53 -0500 Subject: [PATCH] Add trusted-publishing workflow for PyPI publish.yml uploads the wheel on v* tags (or workflow_dispatch) via OIDC. No API token. First v0.1.0 publish is a manual run because that tag already exists. RELEASING.md has the one-time PyPI / GitHub environment setup. --- .github/workflows/publish.yml | 53 +++++++++++++++++++++++++++++++++++ RELEASING.md | 51 +++++++++++++++++++++++++-------- 2 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..3143f39 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,53 @@ +# Publishes roamhq to PyPI via trusted publishing (OIDC). No API token. +# +# One-time PyPI setup (cannot be done from this repo): +# https://pypi.org/manage/account/publishing/ +# project: roamhq +# owner: WonderInventions +# repository: roam-sdk-python +# workflow: publish.yml +# environment: pypi +# +# Also create a GitHub environment named `pypi` on this repo (Settings → +# Environments). Required reviewers are optional but recommended. +# +# First publish of v0.1.0: Actions → Publish → Run workflow, because that +# tag already exists. Later releases publish when a v* tag is pushed. + +name: Publish + +on: + push: + tags: + - "v*" + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish: + name: Publish to PyPI + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/project/roamhq/ + permissions: + id-token: write + contents: read + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Build + run: | + python -m pip install --upgrade pip build + python -m build + + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/RELEASING.md b/RELEASING.md index d39599b..6a26c24 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,21 +1,50 @@ # Releasing `roamhq` Python packages publish to PyPI. Merging a regeneration PR does not publish. -Bump the version in `pyproject.toml`, merge, then publish. +Bump the version in `pyproject.toml`, merge, tag `vX.Y.Z`, and let +`.github/workflows/publish.yml` upload the wheel. + +Do not `twine upload` from a laptop. Publishing uses [trusted +publishing](https://docs.pypi.org/trusted-publishers/): GitHub Actions +proves its identity to PyPI. There is no API token in this repo. ## One-time setup -The PyPI name `roamhq` was free as of the first generation. Create the -project on pypi.org under the Wonder Inventions account, then either: +These steps are in the GitHub and PyPI UIs, not in git. + +1. Create a [pypi.org](https://pypi.org/account/register/) account (work + email) and turn on two-factor authentication. Prefer the Wonder + Inventions org if it already exists. +2. In this GitHub repo: **Settings → Environments → New environment**, + name it `pypi`. Optional: add yourself as a required reviewer so a + tag push cannot publish without a click. +3. On PyPI, open + [pending publishers](https://pypi.org/manage/account/publishing/) + and add: + + | Field | Value | + | --- | --- | + | PyPI project name | `roamhq` | + | Owner | `WonderInventions` | + | Repository | `roam-sdk-python` | + | Workflow name | `publish.yml` | + | Environment name | `pypi` | -- configure trusted publishing (OIDC) for `WonderInventions/roam-sdk-python` - and workflow `publish.yml`, or -- store a PyPI token as a repo secret and add a publish workflow. + The names must match this workflow and the GitHub environment exactly. + The first successful upload creates the PyPI project. + +`roamhq` was free on PyPI as of the first generation (`roam-sdk` is taken). ## Cutting a release -1. Merge the "Regenerate SDK from OpenAPI spec" PR after setting the version - in `pyproject.toml`. -2. Tag `vX.Y.Z` to match. -3. Publish the wheel (`python -m build && twine upload dist/*`, or the - GitHub Action). +1. Merge the "Regenerate SDK from OpenAPI spec" PR after setting the + version in `pyproject.toml`. +2. Tag `vX.Y.Z` to match (`git tag vX.Y.Z && git push origin vX.Y.Z`). + That runs **Publish**. +3. If the environment requires a reviewer, approve the deployment. + +The first `v0.1.0` tag already exists, so it will not retrigger on its +own. After this workflow is on `master`, publish that version with +**Actions → Publish → Run workflow**. + +When it succeeds: https://pypi.org/project/roamhq/ and `pip install roamhq`.