Skip to content

[FEATURE] Branching strategy Phase 2.B - release trigger and versioning docs#557

Open
John McCall (lowlydba) wants to merge 15 commits into
mainfrom
533-devops-branching-strategy---phase-2b---release-versions
Open

[FEATURE] Branching strategy Phase 2.B - release trigger and versioning docs#557
John McCall (lowlydba) wants to merge 15 commits into
mainfrom
533-devops-branching-strategy---phase-2b---release-versions

Conversation

@lowlydba

@lowlydba John McCall (lowlydba) commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 2.B of the branching strategy (#533): per-package release detection on main, plus the versioning and contributor docs. Publishing to PyPI is Phase 3 (#509).

Full design and rationale: docs/versioning.md and CONTRIBUTING.md.

What this adds

  • Per-package releases.
    • Each package under packages/* versions independently and gets its own release series, tagged <package>-v<major>.<minor>.0.
    • Since consumers pin only overture-schema, this stays invisible downstream in our current usage patterns.
  • release-trigger workflow.
    • On merge to main, cuts a published GitHub Release for each package whose major.minor bumped.
    • Patch-only merges go to internal CodeArtifact, not PyPI.
  • Changelog via towncrier 🔔
    • Towncrier is essentially antsibull (the original inspiration for this changelog approach), minus the Ansible parts.
    • TL;DR - you add changelog fragments for each PR (changelog.d/), then before cutting a release run a command that merges all fragments into a changelog, which then feeds release notes.

Decisions

Resolves the TBDs from #533/#509 and this PR's review feedback:

  1. ✅ Per-package releases, not a single umbrella tag.
  2. ✅ Patch merges publish to CodeArtifact only; PyPI is reserved for major.minor bumps.
  3. towncrier fragments over manual notes or auto-generated changelogs.
  4. ⌛ Published release on merge; the human approval gate lives at the Phase 3 PyPI publish (GitHub Environment approval), not a draft release.
  5. ❌ No semantic-release / release-please; they conflict with the human-owns-major/minor model from Phase 2.A.

Notes

Closes #533

Detects an umbrella overture-schema major/minor bump on main and creates
a draft GitHub Release at v<major>.<minor>.0. Publishing the draft is the
only trigger for the public PyPI publish (Phase 3).

Decisions locked: patch builds stay CodeArtifact-only; release notes are
authored manually at release time; only the umbrella package bump cuts a
release.

Closes #533

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
…ases

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
…ft release tag

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
@lowlydba
John McCall (lowlydba) marked this pull request as ready for review July 14, 2026 14:54
Copilot AI review requested due to automatic review settings July 14, 2026 14:54
@lowlydba
John McCall (lowlydba) requested a review from a team as a code owner July 14, 2026 14:54

This comment was marked as outdated.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
@vcschapp

Victor Schappert (vcschapp) commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

👀 Trying to come back up to speed on this.

John McCall (@lowlydba) Unblocking this is my main priority for this week. It'll take me some time to come back up to speed and also do a bit of progressive work aimed setting this process into the overall versioning strategy, but I'm very much on it this week.

@vcschapp

Copy link
Copy Markdown
Collaborator

This is my current understanding of the state. (Same diagram I just posted on the parent tracking issue #509, but with changes marking the deviations from plan that are specific to this PR. (Note: Diagram is LLM-generated.)

2026-07-20-Overture-schema-devops-branching-strategy-PR-557-phase-2 B

Let me know if anything should be corrected.

@vcschapp

Copy link
Copy Markdown
Collaborator

Thanks for this John McCall (@lowlydba). The progress so far is awesome, and only really being held back by slow reviewers.

Posting my conceptual level thoughts answering items listed in the description below. I'll do one comment per point. Once we're aligned on conceptual should be quick to do the concrete review.

@vcschapp

Copy link
Copy Markdown
Collaborator
  1. Patch destination: CodeArtifact only (Option B in [Devops] Branching Strategy - Phase 3 #509). Publishing a GitHub Release is the sole trigger for public PyPI. Keeps the public release signal curated; every main merge is not a public event.

I'd rather have a version number change in pyproject.toml (with a mandatory attached change log file) be the trigger for automated releasing. It keeps the entire release management as part of the code versioning and PR review process and gives more opportunities for automation.

@vcschapp

Victor Schappert (vcschapp) commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator
  1. Umbrella-only release trigger (deviation from "any package"). The issues said any package's major/minor bump cuts a release, but a single v<major>.<minor>.0 tag can't represent two packages bumping to different versions — e.g. a cli 0.1→0.2 bump would have cut a misleading v0.2.0. Only the umbrella overture-schema bump now cuts a release; its version names the tag. Escape hatch: a non-core package needing public PyPI immediately bumps the umbrella minor in the same PR (one line, and honest — the umbrella distribution's contents changed). Otherwise it rides the next umbrella release.

Our intention for the package architecture is to version each package independently.

I suspect this change relates to Alex's issue #558; and possibly also to the issue of how to maintain separate GitHub releases and tags for different packages within a monorepo.

IMO neither of these issues should be blockers for independently versioning the different packages.

Alex's issue #558

I shouldn't think this would be a huge problem for Alex Iannicelli (@atiannicelli) and the data pipeline team because they should only need to depend on overture-schema and worry about the singular version number of that package, but I'm still hoping to hear a reply back from Alex on the issue.

Maintaining separate releases and tags

Up to now, we've only had a single "sequence" of GitHub releases and release tags that version the schema as a whole.

# Release title Tag Date
1. Preview Release v0.4.0 2023-06-15
2. Preview Release v0.5.0 2023-10-18
3. Schema v0.6.0 release v0.6.0 2023-11-14
4. Schema v0.7.0 release v0.7.0 2023-12-13
5. Schema v0.8.0 release v0.8.0 2024-02-14
6. Schema v0.9.0 release v0.9.0 2024-03-12
7. Schema v0.10.0-beta release v0.10.0-beta 2024-04-17
8. Schema v0.11.0-beta release v0.11.0-beta 2024-05-15
9. v0.12.0-beta v0.12.0-beta 2024-06-12
10. v1.0.0 v1.0.0 2024-07-17
11. v1.1.0 v1.1.0 2024-08-19
12. v1.2.0 v1.2.0 2024-10-15
13. v1.3.0 v1.3.0 2024-11-08
14. v1.4.0 v1.4.0 2024-12-17
15. v1.5.0 v1.5.0 2025-01-22
16. v1.6.0 v1.6.0 2025-02-19
17. v1.7.0 v1.7.0 2025-03-19
18. v1.8.0 v1.8.0 2025-04-02
19. v1.9.0 v1.9.0 2025-05-21
20. v1.10.0 v1.10.0 2025-06-25
21. v1.11.0 v1.11.0 2025-07-23
22. v1.12.0 v1.12.0 2025-09-18
23. v1.13.0 v1.13.0 2025-10-17
24. v1.14.0 v1.14.0 2025-11-19
25. v1.15.0 v1.15.0 2025-12-17
26. v1.16.0 v1.16.0 2026-02-12
27. v1.17.0 v1.17.0 2026-05-14

At first glance, it may seem like versioning multiple packages in a monorepo doesn't work well within the GitHub release paradigm, but in practice it's very doable: we just need one tag-and-release "series" for every package.

There are different ways we could do this, but here's a scheme I think would work well:

  • Tag name = package name with -<SEMVER> suffix.
    • e.g., overture-schema-vA.B.C for the overture-schema package
    • e.g., overture-schema-system-vD.E.F for the overture-schema-system package
  • Release title = package name in backticks, space,
    • e.g. overture-schema vA.B.C
    • e.g. overture-schema-system vD.E.F.

@vcschapp

Copy link
Copy Markdown
Collaborator
  1. Changelog: manual notes at release time. No fragment files or auto-generation machinery. Evaluated per-PR fragments (antsibull pattern) and GitHub auto-generated notes; rejected for friction/quality respectively.

Agreed that GitHub auto-generated notes have terrible quality and won't work—and they moreover probably wouldn't work for per-package releases.

I very much like the idea of every PR coming with an antsibull-style changelog fragment for each PR, enforced with a GH action, enabling the final release notes to be fully auto-generated.

The process would be essentially that every PR that touches one of the Python package trees would require a changelog fragment under that tree, e.g.:

packages/
   overture-schema/
      changelog/
          fragments/
              - 535-add-provider-resource-and-version-to-sources.yaml
              - ...

This would allow the releases to be fully auto-generated from the version bumps and should also be helpful in addressing the somewhat frequent complaint that the content of an upcoming schema release is opaque/difficult to dosciver.

John McCall (@lowlydba) You mentioned this being too much friction. Can you elaborate?

@vcschapp

Copy link
Copy Markdown
Collaborator
  1. Draft-release human gate. The bump merge creates a draft release; a maintainer writes notes and clicks Publish, and only that release: published event fires the Phase 3 publish. Pairs the manual-notes decision with a natural approval gate — no accidental public releases.

This ends up being added friction - to create a release we now need the authoritative version bump PRs and then still have to manually go retrieve the changes and write them up as notes.

Per-package versioning can also produce many release drafts so there's added work here (one release draft/package) and potential to miss something.

If we want a simpler manual release gate "just to make sure" we could have the GH action a "review issue" mid-run and require a designated approver to indicate "approve" or some such on it before the publish actions are taken?

@lowlydba
John McCall (lowlydba) marked this pull request as draft July 21, 2026 18:54
…changelog

- release-trigger: detect per-package major.minor bumps on main and cut a
  published GitHub Release per package (tag `<package>-v<major>.<minor>.0`,
  notes extracted from that package's CHANGELOG.md; umbrella marked Latest)
- require-changelog-fragment: new PR check enforcing a changelog update on any
  major.minor bump (accepts a towncrier fragment or a built CHANGELOG.md)
- towncrier: centralize [tool.towncrier] in root pyproject.toml; per-package
  changelog.d/ with a DRY README that defers to docs/versioning.md (no .gitkeep)
- docs/versioning.md: Diataxis rewrite (reference/how-to/why) with a TOC
- CONTRIBUTING.md: lean guiding-light rewrite (217 -> 91 lines); richer,
  workflow-accurate gitGraphs
- publish-python-packages: add contents: read for reusable-workflow checkout

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
Wrap each release path (main->patch, main->minor, vnext->major) in a
collapsible <details> section with its own workflow-accurate gitGraph.
Drop the branch-protection bullet and reduce the CI notes to authoritative
links to the vnext-compat and pr-advisory workflows, which comment their
own fix steps inline.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
… a PR

Add how/when each release path reaches consumers (patch rides the next
release to PyPI via the umbrella; minor and major publish to PyPI on merge).
Reword the Opening a PR CI notes to point at the checks without narrating.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
Move the inline detect heredoc and the extract_notes heredoc out of
release-trigger.yaml into .github/workflows/scripts/detect_version_bumps.py
and extract_release_notes.py, matching the existing package-versions.py
convention. The workflow steps now just invoke them, so the Python is
lint-covered, testable, and free of heredoc quoting. Behavior is unchanged.

Also vary the CONTRIBUTING release diagrams across distinct packages
(places/base/transportation themes) and note that a no-bump merge still
publishes a patch to internal CodeArtifact.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
… any package change

Extract the release-creation logic into a reusable composite action,
.github/actions/create-package-release, with a typed input contract and a
dry-run mode. release-trigger now runs as two jobs: detect emits the bumped
packages as a JSON step output, and a fail-fast:false matrix job calls the
action once per package, so one bad CHANGELOG cannot block sibling releases.
extract_release_notes.py moves into the action as an internal detail, and
detect_version_bumps.py emits JSON (and uses pathlib for portability).

Broaden the changelog policy: require-changelog-fragment now flags any package
with changed files (excluding its own changelog.d/ and CHANGELOG.md) that lacks
a fragment, not just major/minor bumps. Update docs/versioning.md and
CONTRIBUTING.md to match, and clarify that a no-bump merge still publishes a
patch to internal CodeArtifact that is consumable immediately.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>
@lowlydba

John McCall (lowlydba) commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author
  1. I'd rather have a version number change in pyproject.toml (with a mandatory attached change log file) be the trigger for automated releasing.

👍🏻 Fully aligned, and that is what is now implemented.

The release trigger is a <major>.<minor> change in a package's pyproject.toml; a new Changelog fragment verification check makes the attached towncrier changelog fragment mandatory.

Release management stays entirely inside code versioning + PR review, with no out-of-band "publish" action.

@lowlydba

Copy link
Copy Markdown
Contributor Author
  1. Our intention for the package architecture is to version each package independently ... Tag name = package name with -<SEMVER> suffix ... Release title = package name in backticks, space, <SEMVER>.

Adopted as described. release-trigger now detects a bump in any package (not just the umbrella) and cuts one published Release per bumped package:

  • tag <package>-v<semver> (e.g. overture-schema-v1.18.0, overture-schema-system-v0.2.0)
  • title `<package>` <semver> (e.g. `overture-schema` 1.18.0)

The umbrella overture-schema release is flagged Latest; the others are not. Historical bare vX.Y.Z tags are left as a one-time discontinuity. One nuance to confirm: the title carries the bare semver (1.18.0), while the v prefix lives only in the tag. Happy to add v to the title too if you prefer it to match your example exactly.

#558 (pipeline consumers depending only on the umbrella) is tracked separately and is not a blocker here.

@lowlydba

John McCall (lowlydba) commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author
  1. ... a change log file per PR per affected package ... antsibull-style ... auto-generate release notes. Can you elaborate on the friction you saw here?

Agreed on the pattern, and it is in. To your friction question: the friction I flagged earlier was more or less a gut check from my past experiences. Personally, although sometimes it annoys me, I think this approach produces really high quality release notes - Lets Go!

Two notes on how it landed:

  • Tooling: we use towncrier rather than antsibull. Same per-PR-fragment model, but it is well-maintained, Python-native, and assembles notes with a single towncrier build at bump time.
  • Fragment location: packages/<pkg>/changelog.d/<id>.<type>.md (towncrier's convention) instead of changelog/fragments/*.yaml.
    • I didn't look into customizing the locale of these, for lack of motivation, but probably customizable if there are feelings contrary
  • Scope: broadened to require a fragment on any change to a package, not just version bumps, so the changelog is always complete (patch/internal work uses the misc type).
    • This felt like the spirit of the approach, because even patch changes can ruin production ;)

Config is centralized in the root pyproject.toml; per-package builds pass --config pyproject.toml --dir packages/<pkg>. Light usage docs are in docs/versioning.md and the changelog.d/README.md keepers.

@lowlydba

John McCall (lowlydba) commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author
  1. ... the draft release gate felt like friction. What if instead there were a review issue mid-run with a designated approver?

Agreed the draft-release gate was friction, so we dropped it. The release is published directly by the workflow with auto-assembled notes, so there is no manual note-writing and no per-package draft to babysit.

For the human checkpoint you are after, we can use a GitHub Environment approval (native required-reviewers gate) on the Phase 3 PyPI publish job rather than a mid-run review issue. Same designated-approver semantics, less machinery, and it sits at the real public-publish boundary instead of on every internal release. Tracked in #509 (Phase 3 - non-blocking for this PR)

…strategy---phase-2b---release-versions

# Conflicts:
#	.github/workflows/publish-python-packages.yaml

Signed-off-by: John McCall <john@overturemaps.org>
…with any-change policy

The new overture-schema-pyspark package (merged from main) lacked a
changelog.d/ keeper. Add one so the fragment check and towncrier treat it
like the other packages. Also correct the stale 'per user-facing change'
line in all keepers to match the any-change policy in docs/versioning.md.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Signed-off-by: John McCall <john@overturemaps.org>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mostly have questions that might clarify the docs, but I do have a concern about patch version handling, since not publishing those to PyPI would prevent us from publishing bug fixes without promoting them to minor releases.

Comment thread docs/versioning.md Outdated
Comment thread docs/versioning.md
Comment thread docs/versioning.md
| Component | Owner | Set by |
|-----------|-------|--------|
| `<major>.<minor>` | Human | Edited in `pyproject.toml` via a reviewed PR. |
| `<patch>` | CI | [`compute-version`](../.github/actions/compute-version/action.yml) at publish time. The `pyproject.toml` patch is only a floor. |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pyproject.toml patch is only a floor.

Does that mean pyproject.toml can fall out of date if compute-version builds a newer version than is declared (and publishes it)?

Comment thread docs/versioning.md
| Event | Version | Destination |
|-------|---------|-------------|
| Push to `vnext` | `<last-published>+dev.<run#>` | CodeArtifact (dev) |
| Push to `main`, no bump | `<major>.<minor>.<next-patch>` | CodeArtifact |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, explicitly: any push to main (by closing PRs) will publish a new package to CodeArtifact? So a storm of merges will produce a flurry of packages?

I would almost expect +<something> treatment of those so we can flow patch releases to PyPI monotonically.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a storm of merges will produce a flurry of packages?

I think so, but for the internal CodeArtifact haven't we've decided to accept this in order to ensure internal Overture players always have a pre-release build they can work on?

Comment thread docs/versioning.md
|-------|---------|-------------|
| Push to `vnext` | `<last-published>+dev.<run#>` | CodeArtifact (dev) |
| Push to `main`, no bump | `<major>.<minor>.<next-patch>` | CodeArtifact |
| `major.minor` bump on `main` | `<major>.<minor>.0` | Public PyPI |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explicitly (for posterity, not just the PR): PyPI will never receive non-.0 patch packages (automatically)?

Patch merges publish to CodeArtifact only; PyPI is reserved for major.minor bumps.

This reads as decided within the PR description, but it seems problematic to me, since it makes it difficult-to-impossible to publish bug fixes without promoting them to minor versions.

My proposal: extend the major/minor convention to patch — a deliberate patch bump publishes to PyPI like any other bump — and send every no-bump merge to CodeArtifact as +main.N (the + from above). It changes "CI owns the patch version" only by redefining it: CI owns the +main.N interim counter, the human owns the released version.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1.

Comment thread docs/versioning.md
1. Bump `<major>.<minor>` in the package's `pyproject.toml` (reset patch to `0`),
then run `uvx towncrier build --config pyproject.toml --dir packages/<package>`
from the repo root to fold its fragments into `CHANGELOG.md`. Minor bumps
target `main`; major bumps go via `vnext` and reach `main` through a release

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's a "release merge"? (Is there something this could link to?)

@lowlydba John McCall (lowlydba) Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A merge that causes a release? Not sure it warrants a line item but we can :) It isn't a concept, just a colloquial phrase. Feel free to suggest alternatives.

The tables above explain what causes a merge, so its just "when you merge, and it causes a release..." in short form.

Comment thread docs/versioning.md
type), under the affected package:

```
packages/<package>/changelog.d/<issue-or-pr>.<type>.md

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does towncrier determine where in the CHANGELOG to place fragements? Does it look at the commit where this file was introduced?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd check their docs! Not sure off hand.

Comment thread docs/versioning.md Outdated
Comment thread packages/overture-schema-addresses-theme/changelog.d/README.md Outdated
Comment thread packages/overture-schema/changelog.d/557.misc.md Outdated
@vcschapp

Copy link
Copy Markdown
Collaborator
  1. I'd rather have a version number change in pyproject.toml (with a mandatory attached change log file) be the trigger for automated releasing.

👍🏻 Fully aligned, and that is what is now implemented.

The release trigger is a <major>.<minor> change in a package's pyproject.toml; a new Changelog fragment verification check makes the attached towncrier changelog fragment mandatory.

Release management stays entirely inside code versioning + PR review, with no out-of-band "publish" action.

I'm largely good with this but I echo Seth's concern about <major>.<minor> being the release trigger. I believe the <patch> component should be included in the trigger. We want the ability to release patches that include innocuous things like bug fixes and doc changes and to differentiate these from minor releases.

I commented similarly on May 24 in the Phase 2.A PR (#534) but likely the comment got missed in the noise.

@vcschapp

Victor Schappert (vcschapp) commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

On versioning the main branch internal artifacts

Apparently (according to certain LLMs I've been talking to), the +devN suffix isn't PEP 440 orderable and so there's no way to make a dependency version declaration like dependencies = ["foo >= 1.2.3"] pick up foo version v1.2.3+dev4.

OTOH, apparently formulating it like v1.2.3.dev4 is PEP 440 orderable and can be opted into with commands like uv pip install foo --prerelease=allow, but the problem with v1.2.3.devN is that it sorts before v1.2.3, so if a package had a dependency like ["foo >= 1.2.3"], uv will always pick v1.2.3 instead of v1.2.3.dev1.

PEP 440 has the concept of a post-release, which is something like v1.2.3.post4. We could reserve post-releases for internal use so that if a dependent package declares a dependency on v1.2.3 and internal CA has v1.2.3.post4, the dependent package would get the latter instead of the former. This would probably work well for the main branch which by assumption doesn't carry breaking changes on it.

I'll post another comment with thoughts on what to do with the vnext branch.

@vcschapp

Copy link
Copy Markdown
Collaborator

On versioning the vnext branch internal artifacts

In my mind the fundamental question with having both main and vnext is that we likely want two different versioning streams, because:

  • The latest artifact built from main represents the freshest artifact that does not contain a "major" (likely breaking) change. Being able to opt in to this will be useful for internal users like central data pipeline.
  • The latest artifact built from vnext represents the freshest artifact that does have a "major" (likely breaking) change. Again, being able to opt in to this specific version is useful.

So you probably want two different streams of version numbers.

IMO one of the two streams can be done with the post-release .postN PEP 440 components; above I suggested that we use it for main branch. My logic here is that using the post-release sequencing on an existing version number makes the most sense for a change that's supposed to be non-breaking, non-invasive. The nice thing about .postN for minor changes is that the version numbers "just work" the way you would expect.

So what do we use for the vnext stream?

If we have already used up .postN then we have used up the stream of version numbers that "plays nice" with the existing pyproject.toml. Any other stream of version numbers we use is going to require making synthetic edits to the pyproject.toml files of dependent packages. Here's an illustration of what I mean.

  • overture-schema version S1 depends on overture-schema-transportation-theme version T1.
  • I make a vnext PR that touches overture-schema-transportation-theme, resulting in it being assigned version T2 by the automation.
  • If I want the overture-schema published to internal CodeArtifact to have a dependency on the updated transportation code then the automation has to make a temporary local edit of overture-schema's pyproject.toml` before publishing to update the dependency to be on version T2.
  • But this edit of overture-schema's pyproject.toml to depend on a major change from transportation implies that overture-schema itself had a major change, so it should be published with a new synthetic version S2.
  • This process needs to continue all the way up the dependency graph until all reachable dependent packages have been fixed in this way.

This is all a bit complicated, but unless I'm mistaken I think it's what needs to be done.

If I'm right and this complexity is needed anyway, then I propose the following versioning scheme:

  1. Take the major version M of the package getting auto-bumped during the vnext publish.
  2. Compute the new base version for that package as v<M+1>.0.0.
  3. Add a .devN suffix (also PEP 440 blessed) that represents the next available N in that version number.

Then:

  • Dependency resolution would be done with uv ... --prerelease=allow to enable the .devN versions to be resolved.
  • We would know we're not polluting the v<M+1>.0.0 space because the .devN versions sort before any version number we would assign to a public release, according to PEP 440.

Co-authored-by: Seth Fitzsimmons <sethfitz@amazon.com>
Signed-off-by: John McCall <john@lowlydba.com>
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

🗺️ Schema reference docs preview is live!

🌍 Preview https://staging.overturemaps.org/schema/pr/557/schema/index.html
🕐 Updated Jul 23, 2026 20:24 UTC
📝 Commit f14f5b1
🔧 env SCHEMA_PREVIEW true

Note

♻️ This preview updates automatically with each push to this PR.

Co-authored-by: Seth Fitzsimmons <sethfitz@amazon.com>
Signed-off-by: John McCall <john@lowlydba.com>
Comment thread packages/overture-schema/changelog.d/557.misc.md Outdated
Comment thread packages/overture-schema/changelog.d/557.misc.md Outdated
Signed-off-by: John McCall <john@lowlydba.com>
Co-authored-by: Seth Fitzsimmons <sethfitz@amazon.com>
Signed-off-by: John McCall <john@lowlydba.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Devops] Branching Strategy - Phase 2.B - Release Versions

4 participants