Skip to content

[Devops] Streamlined branching strategy for schema #490

@lowlydba

Description

@lowlydba

♻️ 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:

  1. Branch off main
  2. Open a PR back to main
  3. CI runs automatically and checks your changes are compatible with the breaking branch
  4. 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
  5. 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 devstagingmain 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.

Phases

Phase Title Status
Phase 0 Branch infrastructure Ready to start
Phase 1 CI safety net Ready to start after P0
Phase 2 Versioning & release-trigger logic ⚠️ Decisions required before starting
Phase 3 Package publish workflows Starts after P2
Phase 4 Documentation polish Starts after P3

Phase 0

Pure infrastructure, no code risk. Migrates devmain 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 vnextmain 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)
  • ❔ Phase 2 - Changelog approach

Metadata

Metadata

Labels

automation 🦾Change/enhance automation of a processenhancementNew feature or requestquestionFurther information is requested

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions