From 3de0e61278f3d2de3347bfc1685d9d279c2c983c Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Tue, 29 Sep 2026 12:34:57 -0400 Subject: [PATCH 1/3] docs: correct the release process --- RELEASING.md | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/RELEASING.md b/RELEASING.md index 39549e6..d8f1437 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,20 +1,29 @@ Releasing ========= -Publishing happens in CI through PyPI Trusted Publishing (OIDC). There is no -PyPI token to hold locally, and `make release` is not the release path — it -uploads with a stored credential and skips provenance. +Publishing happens in CI through PyPI Trusted Publishing (OIDC). There is no PyPI token +to hold locally, and `make release` is not the release path — it uploads with a stored +credential and skips provenance. -1. Update the version in **both** `pyproject.toml` and - `segment/analytics/version.py`. The publish workflow validates the release - tag against `pyproject.toml` and fails if the two disagree. -2. Update `HISTORY.md`. -3. `git commit -am "Release X.Y.Z."` (where X.Y.Z is the new version) +1. Update the version in **both** `pyproject.toml` and `segment/analytics/version.py`. + The publish workflow validates the release tag against `pyproject.toml` and fails if + the two disagree. +2. In `HISTORY.md`, change the `Unreleased` heading to `X.Y.Z / YYYY-M-D`. +3. `git commit -am "Release X.Y.Z."` 4. Open a PR and merge it to `master`. -5. Tag the merged commit and push it: - `git tag -a X.Y.Z -m "Version X.Y.Z" && git push --tags` +5. Tag the merged commit — no `v` prefix: + + ``` + git tag X.Y.Z && git push origin X.Y.Z + ``` + 6. Create a **GitHub Release** for that tag. The workflow triggers on `release: published`; pushing the tag by itself does not start it. +7. Approve the `production` environment when the publish job requests review. + +The workflow runs the test matrix, builds with `uv`, and uploads with twine, which +performs the OIDC exchange itself — no flag is needed. -The workflow then runs the test matrix, builds with `uv`, and uploads to PyPI -with `--trusted-publishing=always`. +> **Note:** the workflow runs from the *tagged* commit. If it needs fixing, the tag has +> to be recreated after the fix lands; merging to `master` alone changes nothing for a +> release that is already tagged. From 69753727aa623fe59fc58040a33f9eba96402f47 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Tue, 29 Sep 2026 12:57:39 -0400 Subject: [PATCH 2/3] docs: drop the aside about what the release path is not --- RELEASING.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/RELEASING.md b/RELEASING.md index d8f1437..7ddee82 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -2,8 +2,7 @@ Releasing ========= Publishing happens in CI through PyPI Trusted Publishing (OIDC). There is no PyPI token -to hold locally, and `make release` is not the release path — it uploads with a stored -credential and skips provenance. +to hold locally. 1. Update the version in **both** `pyproject.toml` and `segment/analytics/version.py`. The publish workflow validates the release tag against `pyproject.toml` and fails if From db78ed85764b0ee98ac28b6505bb700fa5e30a47 Mon Sep 17 00:00:00 2001 From: Michael Grosse Huelsewiesche Date: Tue, 29 Sep 2026 13:03:56 -0400 Subject: [PATCH 3/3] build: make version.py the single source of the version pyproject.toml carried its own copy, and the publish workflow validated the tag only against that one. A stale version.py would therefore publish a correctly numbered package whose User-Agent and context.library.version reported the previous release, with nothing failing. hatchling now reads the version from version.py, and the tag check validates against the same file. --- .github/workflows/publish.yml | 12 ++++++------ RELEASING.md | 6 +++--- pyproject.toml | 5 ++++- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fe44367..968e47c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -64,13 +64,13 @@ jobs: exit 1 fi VERSION="${TAG#v}" - PKG_VERSION=$(python -c " - import tomllib - with open('pyproject.toml', 'rb') as f: - print(tomllib.load(f)['project']['version']) - ") + PKG_VERSION=$(sed -nE 's/.*VERSION *= *"([^"]+)".*/\1/p' segment/analytics/version.py) + if [ -z "$PKG_VERSION" ]; then + echo "::error::Could not read VERSION from segment/analytics/version.py" + exit 1 + fi if [ "$VERSION" != "$PKG_VERSION" ]; then - echo "::error::Tag $TAG does not match pyproject.toml version $PKG_VERSION" + echo "::error::Tag $TAG does not match VERSION $PKG_VERSION in segment/analytics/version.py" exit 1 fi diff --git a/RELEASING.md b/RELEASING.md index 7ddee82..535d679 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -4,9 +4,9 @@ Releasing Publishing happens in CI through PyPI Trusted Publishing (OIDC). There is no PyPI token to hold locally. -1. Update the version in **both** `pyproject.toml` and `segment/analytics/version.py`. - The publish workflow validates the release tag against `pyproject.toml` and fails if - the two disagree. +1. Update `VERSION` in `segment/analytics/version.py`. This is the only place the + version lives — hatchling reads it at build time, and the publish workflow validates + the release tag against it. 2. In `HISTORY.md`, change the `Unreleased` heading to `X.Y.Z / YYYY-M-D`. 3. `git commit -am "Release X.Y.Z."` 4. Open a PR and merge it to `master`. diff --git a/pyproject.toml b/pyproject.toml index 79b7600..1025e31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "segment-analytics-python" -version = "2.4.0" +dynamic = ["version"] description = "The hassle-free way to integrate analytics into any python application." readme = "README.md" license = "MIT" @@ -41,6 +41,9 @@ dev = [ "mock>=2.0", ] +[tool.hatch.version] +path = "segment/analytics/version.py" + [tool.hatch.build.targets.wheel] packages = ["segment"]