You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
♻️ This top comment is evergreen, and will evolve to match the current state of this effort.
Branching strategy V1
V1 - superseded by v2
> [!NOTE]
> Branch names used below were chosen for clarity, but can be almost anything. Assume the requisite branch protections/settings will be configured to make all of this feasible.
This is a draft suggestion of a simpler, more automatable branching flow for the schema repository. Consider this as a starting point for changes, please call out concerns/questions.
Two branches
We maintain two long-lived branches:
main, the integration branch. This is where all normal work lands. It is always in a green, releasable state, but it is not a snapshot of the last release - it tracks what the next release will look like.
breaking, a parallel branch where breaking changes accumulate between releases. It stays continuously in sync with main so it never drifts. This is opposed to the current approach main_2026_02_12, where its a long-lived breaking branch per release.
graph LR
A[feature/*] -->|squash merge\n nonbreaking PR| B[main]
A -->|squash merge \nbreaking PR | C[breaking]
B -->|CI auto-rebase\n on every merge| C
C -->|merge at release\n + tag v1.x.x| B
Loading
How normal work flows
All regular work follows the same pattern:
Branch off main
Open a PR back to main
CI runs automatically and checks your changes are compatible with the breaking branch
If all checks passes and you are up-to-date with main, your PR is squash-merged — your branch history is yours to work however you like, but a single clean commit lands on main
Once merged, breaking is automatically rebased onto the new main
You never need to touch breaking directly.
flowchart TD
A[PR opens to main] --> B[CI: dry-run check\nsimulate squash onto main\ntest breaking rebase]
B --> C{conflict?}
C -->|no| D[Squash merge to main]
C -->|yes| E[Author rebases feature branch\nonto breaking,\npushes to own branch to pre-emptively resolve]
E -->|re-run check| B
D --> F[CI: auto-rebase breaking onto main force-push]
F --> G{failsafe check: rebase fails?}
G -->|yes| H[Open GitHub issue\nassign PR author]
G -->|no| I[Done]
Loading
If your PR fails the compatibility check
Occasionally a change conflicts with work that's staged in breaking. If this happens, CI will post a comment on your PR explaining exactly what to do. The short version: you rebase your own feature branch onto breaking to resolve the conflict, push your branch, and the check re-runs automatically.
You are only ever asked to fix your own branch.
If your PR fails compatibility check post-merge
While unlikely, this failsafe check in CI will automagically open a GitHub issue and assign it to you. Until resolved, the breaking branch will be out of sync with main.
Breaking changes
If your work contains breaking changes, target breaking instead of main when you open your PR. Everything else works the same way — squash merge, CI checks, and so on.
Monthly release
Once a month, the breaking branch is merged into main and the result is tagged as the release. That's it. There's no separate release branch — the tag on main is the release.
By shifting merge conflicts left in our process, this should always result in a clean, simple merge (making it easy to automate more of the core release steps in the future).
flowchart LR
A[breaking\n] -->|merge into main| B[main\nnow includes breaking changes]
B -->|tag v1.x.0| C[release\ntagged commit on main]
Loading
What this means for contributors
Always branch from main
Target main for normal changes, breaking for breaking changes
Use whatever commit style you like on your branch — only the final squashed commit lands on shared branches
If CI flags a conflict, follow the instructions in the comment — it will tell you exactly what to run
Never push directly to main or breaking
Branching Strategy V2
After discourse/feedback, see the comment below with a V2 iteration
Child issues on this ticket will implement phased changesets to bring us towards the desired state, allocating time and sequencing for still TBD decisions (i.e. around individual package versioning).
Overview
Streamlined branching strategy and release automation for the schema repository. Replaces the current dev → staging → main manual flow and per-release long-lived branches (e.g. main_2026_02_12) with a two-branch model, automated CI safety nets, and a single-action release trigger.
Two-branch model (end state)
main - integration branch. All normal work lands here. Always releasable.
vnext - accumulates major changes between releases. Stays continuously rebased onto main. Merges to main at release time.
Pure infrastructure, no code risk. Migrates dev → main as default branch, retargets open PRs, creates vnext, configures branch protections.
Phase 1
Adds automated PR compatibility checks (dry-run rebase of vnext), post-merge auto-rebase of vnext onto main, and an advisory PR target check.
Phase 2 — Versioning & release-trigger logic ⚠️
Defines the per-package version scheme (<major>.<minor> git-controlled, <patch> CI-computed from CodeArtifact) and the vnext→main release process. Requires team decisions before implementation:
Baseline <major>.<minor> versions for all 12 packages
Changelog approach (per-PR fragments, auto-generated from PR metadata, or manual)
Phase 3
Implements build + publish automation to CodeArtifact (dev + release repos) and public PyPI.
Phase 4
Editorial pass on docs/branching-strategy.md + docs/versioning.md. Adds diagrams, walkthroughs, and FAQ. No new procedures.
Open questions
❔ Do we need to resolve below Phase 2 questions before starting on Phase 0 & 1?
❓ Phase 2 - Baseline <major>.<minor> versions for all 12 packages in packages/* — what version scheme & how to define versions (see Phase 2 issue for initial suggestion)
♻️ This top comment is evergreen, and will evolve to match the current state of this effort.
Branching strategy V1
V1 - superseded by v2
> [!NOTE] > Branch names used below were chosen for clarity, but can be almost anything. Assume the requisite branch protections/settings will be configured to make all of this feasible.This is a draft suggestion of a simpler, more automatable branching flow for the schema repository. Consider this as a starting point for changes, please call out concerns/questions.
Two branches
We maintain two long-lived branches:
main, the integration branch. This is where all normal work lands. It is always in a green, releasable state, but it is not a snapshot of the last release - it tracks what the next release will look like.breaking, a parallel branch where breaking changes accumulate between releases. It stays continuously in sync withmainso it never drifts. This is opposed to the current approachmain_2026_02_12, where its a long-lived breaking branch per release.graph LR A[feature/*] -->|squash merge\n nonbreaking PR| B[main] A -->|squash merge \nbreaking PR | C[breaking] B -->|CI auto-rebase\n on every merge| C C -->|merge at release\n + tag v1.x.x| BHow normal work flows
All regular work follows the same pattern:
mainmainbreakingbranchmain, your PR is squash-merged — your branch history is yours to work however you like, but a single clean commit lands onmainbreakingis automatically rebased onto the newmainYou never need to touch
breakingdirectly.flowchart TD A[PR opens to main] --> B[CI: dry-run check\nsimulate squash onto main\ntest breaking rebase] B --> C{conflict?} C -->|no| D[Squash merge to main] C -->|yes| E[Author rebases feature branch\nonto breaking,\npushes to own branch to pre-emptively resolve] E -->|re-run check| B D --> F[CI: auto-rebase breaking onto main force-push] F --> G{failsafe check: rebase fails?} G -->|yes| H[Open GitHub issue\nassign PR author] G -->|no| I[Done]If your PR fails the compatibility check
Occasionally a change conflicts with work that's staged in
breaking. If this happens, CI will post a comment on your PR explaining exactly what to do. The short version: you rebase your own feature branch ontobreakingto resolve the conflict, push your branch, and the check re-runs automatically.You are only ever asked to fix your own branch.
If your PR fails compatibility check post-merge
While unlikely, this failsafe check in CI will automagically open a GitHub issue and assign it to you. Until resolved, the
breakingbranch will be out of sync withmain.Breaking changes
If your work contains breaking changes, target
breakinginstead ofmainwhen you open your PR. Everything else works the same way — squash merge, CI checks, and so on.Monthly release
Once a month, the
breakingbranch is merged intomainand the result is tagged as the release. That's it. There's no separate release branch — the tag onmainis the release.By shifting merge conflicts left in our process, this should always result in a clean, simple merge (making it easy to automate more of the core release steps in the future).
flowchart LR A[breaking\n] -->|merge into main| B[main\nnow includes breaking changes] B -->|tag v1.x.0| C[release\ntagged commit on main]What this means for contributors
mainmainfor normal changes,breakingfor breaking changesmainorbreakingBranching Strategy V2
After discourse/feedback, see the comment below with a V2 iteration
Child issues on this ticket will implement phased changesets to bring us towards the desired state, allocating time and sequencing for still TBD decisions (i.e. around individual package versioning).
Overview
Streamlined branching strategy and release automation for the schema repository. Replaces the current
dev→staging→mainmanual flow and per-release long-lived branches (e.g.main_2026_02_12) with a two-branch model, automated CI safety nets, and a single-action release trigger.Two-branch model (end state)
main- integration branch. All normal work lands here. Always releasable.vnext- accumulates major changes between releases. Stays continuously rebased ontomain. Merges tomainat release time.Phases
Phase 0
Pure infrastructure, no code risk. Migrates
dev→mainas default branch, retargets open PRs, createsvnext, configures branch protections.Phase 1
Adds automated PR compatibility checks (dry-run rebase of
vnext), post-merge auto-rebase ofvnextontomain, and an advisory PR target check.Phase 2 — Versioning & release-trigger logic⚠️
Defines the per-package version scheme (
<major>.<minor>git-controlled,<patch>CI-computed from CodeArtifact) and thevnext→mainrelease process. Requires team decisions before implementation:<major>.<minor>versions for all 12 packagesPhase 3
Implements build + publish automation to CodeArtifact (dev + release repos) and public PyPI.
Phase 4
Editorial pass on
docs/branching-strategy.md+docs/versioning.md. Adds diagrams, walkthroughs, and FAQ. No new procedures.Open questions
<major>.<minor>versions for all 12 packages inpackages/*— what version scheme & how to define versions (see Phase 2 issue for initial suggestion)