Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,32 @@ jobs:
NEW_VERSION="${{ steps.check_release.outputs.new_version }}"

if [[ ! "$NEW_VERSION" =~ ^${BRANCH_MAJOR}\. ]]; then
echo "::error::Version $NEW_VERSION doesn't match branch constraint ${BRANCH_MAJOR}.x"
echo "Stable branches should only receive patch and minor releases."
echo "Use a BREAKING CHANGE footer on main to bump the major version."
# Find the latest non-prerelease tag PSR used as baseline.
LATEST_STABLE_TAG=$(git tag --list 'v*' --merged HEAD \
| grep -v -- '-dev' \
| grep -v -- '.dev' \
| sort -V \
| tail -1 || true)

echo "::error::Computed version $NEW_VERSION does not match branch constraint ${BRANCH_MAJOR}.x"
echo ""
echo "python-semantic-release computes the next stable version from the latest"
echo "non-prerelease tag reachable from HEAD. Prerelease tags (vX.Y.Z-dev.N) are ignored."
echo ""
echo "Latest non-prerelease tag PSR used as baseline: ${LATEST_STABLE_TAG:-<none found>}"
echo ""
echo "Likely causes:"
echo " 1. No seed tag exists for the previous major (expected v$((BRANCH_MAJOR-1)).x.y)."
echo " → Create one at the last v${BRANCH_MAJOR}.0.0-dev.N commit and push it:"
echo " git tag v$((BRANCH_MAJOR-1)).0.0 <commit>"
echo " git push origin v$((BRANCH_MAJOR-1)).0.0"
echo " Then re-run this workflow."
echo ""
echo " 2. Legacy non-prerelease tags from an unrelated previous package are"
echo " shadowing the seed. Delete them (after confirming with maintainers):"
echo " git push origin :refs/tags/<old-tag>"
echo ""
echo "See RELEASE.md → 'Creating a New Stable Branch' for the full procedure."
exit 1
fi

Expand Down
30 changes: 29 additions & 1 deletion RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,38 @@ BREAKING CHANGE: SDK major version bumped from 9 to 10 to track Camunda server 8
git push -u origin stable/10
```

The `BREAKING CHANGE` footer is required because all the bump-triggering commits are before the latest dev tag on `main`. This commit gives PSR something to compute from: it sees `BREAKING CHANGE` after `v9.0.0-dev.N` → major bump → `10.0.0` on a non-prerelease branch.
> **Critical — seed tag required**: `python-semantic-release` computes the next stable version from the latest **non-prerelease** tag in the branch's history. Prerelease tags (`vN.Y.Z-dev.N`) are **ignored** for this calculation. If the most recent non-prerelease tag is not the immediately previous stable major (e.g. `v9.x.y` before cutting `stable/10`), PSR will walk further back in history and compute the wrong version.
>
> For example, if only `v1.x` legacy tags exist when `stable/9` is first cut, PSR applies the `BREAKING CHANGE` bump against `1.1.3` and produces `2.0.0` — which fails the `Validate version matches stable branch` gate.
>
> **Before pushing the stable branch**, confirm that a `v<previous-major>.x.y` non-prerelease tag exists:
>
> ```bash
> git tag --list 'v*' | grep -v -- '-dev' | sort -V | tail -5
> ```
>
> If no suitable seed tag exists (e.g. first-time stable cutover, or prior history only has unrelated legacy tags), create one pointing at the last dev-release commit of the previous line before pushing `stable/N`:
>
> ```bash
> # Example: seed v9.0.0 at the v9.0.0-dev.N commit before cutting stable/10
> git tag v9.0.0 <commit-of-last-9.0.0-dev.N>
> git push origin v9.0.0
> ```

CI runs automatically on push and publishes the first stable release (e.g. `10.0.0`).

#### Recovery: if the release workflow fails with a version mismatch

Symptom: the `Validate version matches stable branch` step fails with a message like `Version 2.0.0 doesn't match branch constraint 10.x`.

This means PSR fell back to a too-old baseline tag (see the note above). To recover:

1. Identify the commit that should have been the previous stable (typically the last `vN-1.0.0-dev.*` commit on `main`).
2. Create and push the seed tag: `git tag vN-1.0.0 <commit>` then `git push origin vN-1.0.0`.
3. Re-run the failed `Publish` workflow.

Do **not** hand-stamp the new major version in `pyproject.toml` on the stable branch as a workaround — PSR still uses tags, not the pyproject version, to compute the bump, so the mismatch will recur on the next push.

### 4. Bump `main` to the Next Major

```bash
Expand Down