Goal
Implement CI release-event detection and the release process for main.
Scope: release trigger + vnext/main merge process + changelog machinery + docs. No publish workflows, those live in Phase 3 (#509), which this phase unblocks.
Implemented in PR #557.
Model (as implemented)
Humans own the full <major>.<minor>.<patch> in each package's pyproject.toml. Any version increase merged to main is a release; CI only versions the interim internal builds between releases.
- Every PR that changes a package carries a towncrier fragment (
packages/<pkg>/changelog.d/), enforced by CI.
- A release PR bumps the version and runs
towncrier build, folding fragments into that package's CHANGELOG.md (notes reviewed in the PR).
- On merge,
release-trigger cuts one published GitHub Release per bumped package: tag <package>-v<version>, notes read back from CHANGELOG.md. The umbrella overture-schema release is marked Latest.
- No-bump merges get internal builds versioned
<version>.postN+main.<sha> (or +vnext.<sha>), which order after the release for >= consumers and are rejected by public PyPI by construction.
Decisions resolved
| Question |
Decision |
| Patch destination |
Patch is a human bump like any other, releases to PyPI. No-bump merges are internal-only .postN builds. |
| Changelog approach |
towncrier per-PR fragments, folded in the release PR, enforced by a CI check. |
| Release granularity |
Per-package tags (<pkg>-v<semver>); packages version independently. |
| Release gate |
None at the GH Release step; the human gate moves to a GitHub Environment approval on the Phase 3 PyPI publish job. |
| Internal build versioning |
PEP 440 post-releases; +dev.N rejected as not orderable. N is a per-version sequence (.post0 = identical to the release). Verified: >=X.Y.Z resolves .postN, ==X.Y.Z selects the clean release, > never matches (pin with >=). |
| Workspace dependency floors |
uv dual declaration: hand-maintained >= floors in project.dependencies alongside workspace sources. A major bump of a dependency must cascade to its dependents, enforced by CI. |
Definition of done
Original issue body (superseded, kept for history)
Goal (original)
Implement CI release-event detection and the release process for main.
Depends on Phase 2.A (#508), version scheme baseline and compute-version composite action must exist first.
1. Major/minor bump -> public PyPI release
- Human edits
<major>.<minor> in any package's pyproject.toml and opens a PR to vnext (or main for non-breaking).
- PR merges normally.
- For breaking changes: maintainer opens a
vnext->main PR (regular merge, not squash).
- On merge to
main: p2-release-trigger detects the <major>/<minor> bump -> creates GH Release at v<major>.<minor>.0.
- GH Release event fires
p3-pypi-publish (Phase 3) -> all affected packages publish to public PyPI.
2. Normal patch commits -> auto-versioned CA builds
- Push to
vnext: affected packages publish to CA dev as <major>.<minor>.<last-patch>+dev.<N>.
- Push to
main (no bump): affected packages publish to CA as <major>.<minor>.<next-patch>.
Both superseded: patch is now human-owned (releases like any bump), and +dev.N was replaced by .postN because local-only labels are not PEP 440 orderable.
Changelog options evaluated
- Per-PR fragment files assembled at release time (antsibull pattern) -> adopted, via towncrier
- Auto-generated from PR titles/descriptions -> rejected, poor quality
- Manual release notes at release time -> rejected, added friction with no review trail
Goal
Implement CI release-event detection and the release process for
main.Scope: release trigger +
vnext/mainmerge process + changelog machinery + docs. No publish workflows, those live in Phase 3 (#509), which this phase unblocks.Implemented in PR #557.
Model (as implemented)
Humans own the full
<major>.<minor>.<patch>in each package'spyproject.toml. Any version increase merged tomainis a release; CI only versions the interim internal builds between releases.packages/<pkg>/changelog.d/), enforced by CI.towncrier build, folding fragments into that package'sCHANGELOG.md(notes reviewed in the PR).release-triggercuts one published GitHub Release per bumped package: tag<package>-v<version>, notes read back fromCHANGELOG.md. The umbrellaoverture-schemarelease is marked Latest.<version>.postN+main.<sha>(or+vnext.<sha>), which order after the release for>=consumers and are rejected by public PyPI by construction.Decisions resolved
.postNbuilds.<pkg>-v<semver>); packages version independently.+dev.Nrejected as not orderable.Nis a per-version sequence (.post0= identical to the release). Verified:>=X.Y.Zresolves.postN,==X.Y.Zselects the clean release,>never matches (pin with>=).>=floors inproject.dependenciesalongside workspace sources. A major bump of a dependency must cascade to its dependents, enforced by CI.Definition of done
release-triggerworkflow live: detects per-package bumps, fails on version decreases, creates per-package Releasesvnext/mainrelease PR process documented; Phase 1 workflows skip onhead.ref == 'vnext'require-changelog-fragment)compute-versionreworked to.postNinternal builds (per-version sequence from CodeArtifact,.post0first)docs/versioning.mdcreated,CONTRIBUTING.mdupdatedOriginal issue body (superseded, kept for history)
Goal (original)
Implement CI release-event detection and the release process for
main.Depends on Phase 2.A (#508), version scheme baseline and
compute-versioncomposite action must exist first.1. Major/minor bump -> public PyPI release
<major>.<minor>in any package'spyproject.tomland opens a PR tovnext(ormainfor non-breaking).vnext->mainPR (regular merge, not squash).main:p2-release-triggerdetects the<major>/<minor>bump -> creates GH Release atv<major>.<minor>.0.p3-pypi-publish(Phase 3) -> all affected packages publish to public PyPI.2. Normal patch commits -> auto-versioned CA builds
vnext: affected packages publish to CA dev as<major>.<minor>.<last-patch>+dev.<N>.main(no bump): affected packages publish to CA as<major>.<minor>.<next-patch>.Both superseded: patch is now human-owned (releases like any bump), and
+dev.Nwas replaced by.postNbecause local-only labels are not PEP 440 orderable.Changelog options evaluated