Branching and Versioning Strategy¶
This document covers branch naming, PR rules, version format, and the release workflow for contributors.
Branch Model¶
| Branch | Purpose | PR required? | Approval required? |
|---|---|---|---|
main |
Stable trunk. Never commit directly. | Yes | Yes (at least 1) |
feature/<name> |
All feature work. Created from main. Merged back to main via PR. |
Yes | No |
bugfixes/<name> |
Bug fixes. Branch from main for pre-release fixes; branch from a release tag for hotfixes. |
Yes (to main) |
No |
Rules:
feature/branches must be branched offmain.bugfixes/branches branch frommainfor pre-release fixes. For hotfixes to an already-released version, branch from the release tag:git checkout -b bugfixes/fix-foo v5.2.0.- Hotfix commits must be cherry-picked back to
mainvia a separate PR so the fix is included in future releases. - All merges to
maingo through a Pull Request — no direct pushes. - Branch names: lowercase, hyphens. Examples:
feature/risk-score-export,bugfixes/fix-login-redirect. - One issue per branch. Each branch fixes exactly one issue or implements exactly one feature. Never combine unrelated fixes into a single branch or PR.
Starting New Work¶
# Feature or pre-release bugfix — branch from main
git checkout main && git pull
git checkout -b feature/<name>
# or
git checkout -b bugfixes/<name>
# Hotfix to a released version — branch from the release tag, NOT from main
git checkout -b bugfixes/<name> v5.2.0
Version Number Format¶
Two formats, both 4-part (PowerShell-compatible):
| Context | Format | Example |
|---|---|---|
main dev builds (:edge) |
Major.Minor.yyyyMMdd.HHmm |
5.3.20260419.1430 |
Release tags (:latest) |
Major.Minor.Patch.0 |
5.2.1.0 |
Who updates what:
| Action | Who | When |
|---|---|---|
Minor bump + timestamp |
bump-version.yml GitHub Action |
Automatically on every PR merge to main |
| Release version | cut-release.yml GitHub Action |
When you run Actions → Cut Release |
| Hotfix version | cut-hotfix.yml GitHub Action |
When you run Actions → Cut Hotfix |
Major bump |
Developer, via PR to main |
Only for breaking changes |
| Branch work | Nobody | Never touch setup/IdentityAtlas.psd1 on a branch |
Changelog Fragments¶
Every feature/ or bugfixes/ branch must include a changelog fragment. Never edit CHANGES.md directly — the bump-version.yml CI action merges all fragments on PR merge.
File: changes/<descriptive-name>.md (e.g. changes/fix-login-redirect.md)
Format:
- Fixed the login redirect when auth is enabled and no session exists
- Improved error message when tenant ID is missing
Write in user-facing language. One bullet per functional change. Add the file alongside the code change — don't batch at the end.
Merging to Main (via PR)¶
- Open a PR from
feature/<name>orbugfixes/<name>intomain. - Use the changelog fragment content as the PR description body.
- Requires 1 approval and passing CI.
- After merge,
bump-version.ymlautomatically incrementsMinor, updates the timestamp, and merges allchanges/*.mdfragments intoCHANGES.md. Thedocker-publish.ymlaction then builds and pushes Docker images tagged:edge.
Cutting a Release¶
When main is stable and ready to ship to customers:
- Go to Actions → Cut Release → Run workflow
- Enter the version:
Major.Minor.Patch(e.g.5.2.0) - The workflow creates tag
v5.2.0on the currentmainHEAD docker-publish.ymltriggers automatically on the tag push and builds:latest+:5.2.0.0
Customers who track :latest will receive the new version on their next docker compose pull.
Hotfix Releases¶
To ship a bugfix without including features already on main:
# 1. Branch from the release tag — NOT from main
git checkout -b bugfixes/fix-login-crash v5.2.0
# 2. Fix the bug, commit, push
git push origin bugfixes/fix-login-crash
- Go to Actions → Cut Hotfix → Run workflow
- Enter the branch name (
bugfixes/fix-login-crash) and new version (5.2.1) - The workflow creates tag
v5.2.1on the HEAD of your branch docker-publish.ymlbuilds:latest+:5.2.1.0
After the hotfix ships, open a PR to cherry-pick the fix into main:
git checkout main && git pull
git cherry-pick <fix-commit-sha>
gh pr create --base main --title "fix: cherry-pick hotfix from v5.2.1"
Stacked PRs¶
For larger features, break the work into a stack of small focused PRs. Each PR targets the previous branch in the stack:
# Step 1 — targets main
git checkout -b feature/foo-step-1
gh pr create --base main --title "step 1: ..."
# Step 2 — stacked on step 1
git checkout -b feature/foo-step-2
gh pr create --base feature/foo-step-1 --title "step 2: ..."
When a bottom PR merges, retarget the next one: gh pr edit <number> --base main.
Image Channels¶
| Tag | Published when | Who uses it |
|---|---|---|
:latest |
A release tag (v5.2.0) is created via Actions → Cut Release or Cut Hotfix |
Customers (default) |
:edge |
Every PR merges to main |
Developers and testers |
:5.2.0.0 |
Same time as :latest — exact pinned version |
Production deployments needing controlled upgrades |
See Docker Setup for how to select a channel via IMAGE_TAG.