From bd81c289026ef5ea20a1dfe449c9f327596b758d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 11:51:32 +0000 Subject: [PATCH 1/3] Move release procedure out of the READMEs into RELEASING.md The READMEs are the PyPI long description; release/vendoring steps are maintainer docs, not user docs. RELEASING.md also documents the full tag pipeline including the GitHub Release assets job added in #6. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01SQbVkPEprK2ebcjck5ouUy --- README.md | 29 +++------------------- README_JP.md | 28 +++------------------ RELEASING.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 49 deletions(-) create mode 100644 RELEASING.md diff --git a/README.md b/README.md index 9952543..cbed687 100644 --- a/README.md +++ b/README.md @@ -114,28 +114,7 @@ This package bundles a pinned `gomc-rest` binary (currently **v1.4.0**, set in that raises its minimum server version can't be installed without also bumping the bundled binary. -## Releasing / bundled binaries - -The bundled server version is pinned in `GOMC_REST_VERSION`. Binaries are not -committed to git; they are fetched from the matching gomc-rest GitHub release. - -- Locally: `python scripts/vendor_binaries.py` downloads all three binaries - into `src/gomc_rest/binaries/`, verifying each against the trusted SHA-256 - values committed in `checksums/.sha256`. -- On a `v*` tag, `.github/workflows/release.yml` builds one platform-specific - wheel per OS (each bundling only its matching binary) and publishes to PyPI - via trusted publishing. The release job verifies the tag equals - `project.version`; `workflow_dispatch` builds wheels for verification only and - never publishes. - -To cut a release: - -1. To change the bundled server, edit `GOMC_REST_VERSION` (keep it within the - range accepted by the pinned `gomc-rest-client`) and add a matching - `checksums/.sha256` with the trusted SHA-256 of each asset. If the - new binaries change their glibc requirement, update the `plat` tags in - `release.yml` accordingly. -2. Bump the package version in **both** `pyproject.toml` (`project.version`) - and `src/gomc_rest/__init__.py` (`__version__`) — they must match. -3. Tag that exact version, e.g. `git tag v0.2.0 && git push origin v0.2.0` - (the tag must equal `project.version` or the release job fails). +## Development + +Release procedure and bundled-binary maintenance are documented in +[RELEASING.md](https://github.com/Moge800/gomc_rest_python/blob/main/RELEASING.md). diff --git a/README_JP.md b/README_JP.md index ac8cab6..7285af5 100644 --- a/README_JP.md +++ b/README_JP.md @@ -125,28 +125,8 @@ finally: これにより、より新しいサーバーを必要とするクライアントが意図せず インストールされることを防ぎます。 -## リリースと同梱バイナリ +## 開発者向け -バイナリはGitリポジトリへコミットせず、対応するgomc-restのGitHub Releaseから -取得します。 - -- ローカルでは `python scripts/vendor_binaries.py` を実行すると、3種類の - バイナリが `src/gomc_rest/binaries/` にダウンロードされます。各ファイルは - `checksums/.sha256` に記録されたSHA-256ハッシュと照合されます。 -- `v*` タグをpushすると、`.github/workflows/release.yml` がOS別の `wheel` と - クライアント専用の `sdist` をビルドし、PyPIのTrusted Publishingを使用して - 公開します。`workflow_dispatch` では検証用のビルドのみを行い、公開しません。 - -### リリース手順 - -1. 同梱サーバーを変更する場合は `GOMC_REST_VERSION` を更新し、各バイナリの - SHA-256ハッシュを記載した `checksums/.sha256` を追加します。 - 必要なglibcバージョンが変わる場合は、`release.yml` の `plat` タグも更新します。 -2. `pyproject.toml` の `project.version` と - `src/gomc_rest/__init__.py` の `__version__` を同じバージョンへ更新します。 -3. パッケージバージョンと同じタグを作成してpushします。 - -```bash -git tag v0.2.0 -git push origin v0.2.0 -``` +リリース手順と同梱バイナリの管理方法は +[RELEASING.md](https://github.com/Moge800/gomc_rest_python/blob/main/RELEASING.md) +を参照してください。 diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..1456133 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,69 @@ +# Releasing + +Maintainer notes. Users don't need anything here — see [README.md](README.md). + +## What a tag push does + +Pushing a `v*` tag runs `.github/workflows/release.yml`: + +1. **Guard** — the tag must equal `project.version` in `pyproject.toml`, + or every job fails immediately. +2. **Build wheels** (one per platform, each bundling only its matching + server binary, downloaded and SHA-256-verified at build time): + - `win_amd64` — `gomc-rest.exe` + - `manylinux_2_34_x86_64` — `gomc-rest-linux-amd64` (dynamically linked, + needs glibc ≥ 2.34; hence the 2_34 tag) + - `manylinux2014_aarch64` — `gomc-rest-linux-arm64` (statically linked) +3. **Build sdist** — no binary; the client-only fallback for platforms + without a wheel (macOS, Windows arm64, older glibc). +4. **Publish to PyPI** — trusted publishing (OIDC) via the `pypi` + environment. `skip-existing` makes re-running a tag safe. +5. **GitHub Release** — created only after PyPI publish succeeds, with + generated notes and all dist files attached as assets. + +`workflow_dispatch` runs the builds for verification but never publishes. + +## Cutting a release + +1. Bump the package version in **both** places (they must match the tag): + - `pyproject.toml` → `project.version` + - `src/gomc_rest/__init__.py` → `__version__` +2. Merge to `main`, then tag that exact version: + + ```bash + git tag v0.2.0 + git push origin v0.2.0 + ``` + +If publish fails transiently, fix and re-push the same tag — PyPI skips +files it already has, and the release job then attaches the assets. + +## Bumping the bundled gomc-rest server + +Only needed when changing the bundled server version: + +1. Edit `GOMC_REST_VERSION`. Keep it within the range accepted by the + pinned `gomc-rest-client` (its `MINIMUM_SUPPORTED_GOMC_REST_VERSION`); + bump the client pin in `pyproject.toml` together if needed. +2. Add `checksums/.sha256` with the trusted SHA-256 of each + release asset (`gomc-rest.exe`, `gomc-rest-linux-amd64`, + `gomc-rest-linux-arm64`). These are committed so a swapped release + asset is detected; vendoring fails closed without them. +3. If the new binaries change their glibc requirement (check with + `readelf -V | grep GLIBC`), update the `plat` tags in + `release.yml` and the CI floor test image in `ci.yml`. + +## Local builds (testing without PyPI) + +```bash +python scripts/vendor_binaries.py # fetch + verify all binaries +python -m build --wheel +python -m wheel tags --platform-tag manylinux_2_34_x86_64 --remove dist/*.whl +python -m build --sdist # remove binaries first for a clean sdist +``` + +## One-time infrastructure (already done) + +- PyPI trusted publisher: repo `Moge800/gomc_rest_python`, workflow + `release.yml`, environment `pypi`. +- GitHub environment `pypi` on the repository. From d35a74bf0dd927b6a908bf1d03dfb31ab2dd5699 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 11:53:55 +0000 Subject: [PATCH 2/3] RELEASING: re-run the workflow on transient failure, not re-push the tag Per review: git rejects pushing an existing tag; the correct recovery for a transient publish failure is re-running the failed jobs from the Actions UI. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01SQbVkPEprK2ebcjck5ouUy --- RELEASING.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RELEASING.md b/RELEASING.md index 1456133..0975e30 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -35,8 +35,10 @@ Pushing a `v*` tag runs `.github/workflows/release.yml`: git push origin v0.2.0 ``` -If publish fails transiently, fix and re-push the same tag — PyPI skips -files it already has, and the release job then attaches the assets. +If publish fails transiently, re-run the failed jobs for that tag's run +from the GitHub Actions UI — PyPI skips files it already has, and the +release job then attaches the assets. Only delete and recreate the tag if +the fix requires new commits (which means a new version anyway). ## Bumping the bundled gomc-rest server From 53fcb4de2db729cbdcbaac0c850a0b0469a8281e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 12:00:08 +0000 Subject: [PATCH 3/3] RELEASING: make the sdist cleanup path explicit Per review: say where the vendored binaries live instead of 'remove binaries first'. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01SQbVkPEprK2ebcjck5ouUy --- RELEASING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASING.md b/RELEASING.md index 0975e30..2073510 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -61,7 +61,8 @@ Only needed when changing the bundled server version: python scripts/vendor_binaries.py # fetch + verify all binaries python -m build --wheel python -m wheel tags --platform-tag manylinux_2_34_x86_64 --remove dist/*.whl -python -m build --sdist # remove binaries first for a clean sdist +rm src/gomc_rest/binaries/gomc-rest* # drop vendored binaries for a clean sdist +python -m build --sdist ``` ## One-time infrastructure (already done)