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¶
| Context | Format | Example |
|---|---|---|
main dev builds (:edge) |
Major.Minor.yyyyMMdd.HHmm |
5.3.20260419.1430 |
Pre-release tags (:beta) |
Major.Minor.Patch-beta.N |
5.3.0-beta.1 |
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 |
| Pre-release version | cut-beta.yml GitHub Action |
When you run Actions → Cut Beta |
| 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 Pre-Release (Beta / RC)¶
To publish a build for testers without touching :latest:
- Go to Actions → Cut Beta → Run workflow
- Enter the version:
Major.Minor.Patch-beta.N(e.g.5.3.0-beta.1,5.3.0-rc.1,5.3.0-alpha.1) - The workflow creates the tag on the current
mainHEAD docker-publish.ymlbuilds:beta+:5.3.0-beta.1
Users on docker-compose.prod.yml tracking :latest are not affected.
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) |
:beta |
A pre-release tag is created via Actions → Cut Beta | Beta testers |
: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 |
:5.3.0-beta.1 |
Same time as :beta — exact pre-release version |
Testers who want a reproducible pre-release build |
See Docker Setup for how to select a channel via IMAGE_TAG.
Repository Rulesets¶
Branch protection is configured via two GitHub rulesets. If you ever need to recreate them (e.g. after transferring the repo), do so manually in Settings → Rules → Rulesets.
Protect main¶
| Setting | Value |
|---|---|
| Target | main |
| Merge methods | Squash only |
| Required approvals | 1 + code owner review |
| Dismiss stale reviews | Yes |
| Required status checks | PR Summary (strict) |
| Code scanning | CodeQL — errors threshold, high/higher security alerts |
| Deletion | Blocked |
| Force push | Blocked |
Bypass actors:
| Actor | Type | Mode | Why |
|---|---|---|---|
| Fortigi CI bot | Integration | Always | Pushes automated version bump commits on PR merge |
| IdentityAtlas-Owners | Team | Pull request only | Allows team members to merge without a second approval |
Protect gh-pages¶
| Setting | Value |
|---|---|
| Target | gh-pages |
| Deletion | Blocked |
| Force push | Blocked |
No bypass actors — mike (the docs versioning tool) only does regular fast-forward pushes and never needs to delete or force-push the branch.