tsc/process/release-branching.md
Ipstenu (Mika Epstein) 1a168d6127
Add Release Branching Strategy (#190)
Signed-off-by: Mika Epstein ipstenu@halfelf.org
Signed-off-by: Mika Ipstenu Epstein <ipstenu@halfelf.org>
2026-02-02 11:33:12 -06:00

6.8 KiB

Core Principles

  • Main is Production: main only contains tagged, production-ready code.
  • Release Isolation: Feature work is bundled into a specific release/X.Y.Z branch.
  • Development as Integration: The development branch serves as the staging ground where the release is tested in a shared environment.
  • Gated Promotion: Code moves from release/X.Y.Zdevelopment (Testing) → main (Production).

Release Branch Workflow

Overview

flowchart TD
    A[Create release/X.Y.Z from main] --> B[Devs branch from release/X.Y.Z]
    B --> C[PRs merged into release/X.Y.Z]
    C --> D[Release Manager merges release to development]
    D --> E{QA/Testing Passed?}
    E -- No --> B
    E -- Yes --> F[Merge release/X.Y.Z to main]
    F --> G[Tag vX.Y.Z & Delete release branch]
    G --> H[Merge main back to development]

Workflow Steps

1. Create Release Branch

Branch from main using naming: release/X.Y.Z.

This ensures the release starts from a stable production state.

2. Development Phase

Developers create short-lived feature/fix branches from the release branch.

Pull Requests are opened against the release branch, not development or main.

Release Manager/Senior Devs review and merge these into the release branch.

3. Testing & Validation (The "Development" Gate)

The Release Manager merges the release/X.Y.Z branch into the development branch.

The development branch is deployed to the Staging/QA environment.

Crucial: If bugs are found, fixes are made on new branches off release/X.Y.Z and the process repeats.

4. Merge to Main

Once the release branch is verified on development, the Release Manager merges the release branch (not the development branch) into main.

This ensures only the specific, tested release code enters production.

A version tag (e.g., v1.2.0) is applied.

5. Cleanup & Sync

The release branch is deleted.

Main is merged back into development to ensure any hotfixes or version updates are synced for the next cycle.

Branch Lifecycle

gitGraph
    commit id: "v1.0.0"
    branch development
    branch release/1.1.0
    checkout release/1.1.0
    commit id: "Feature A"
    commit id: "Feature B"
    checkout development
    merge release/1.1.0 id: "Testing on Staging"
    checkout release/1.1.0
    commit id: "Bugfix from QA"
    checkout development
    merge release/1.1.0 id: "Final Test"
    checkout main
    merge release/1.1.0 id: "v1.1.0 Production" tag: "v1.1.0"
    checkout development
    merge main id: "Sync Dev"

Branch Protection Rules

+---------------|-------------|---------------|--------------+ | Branch | PR Reviews | Status Checks | Restrictions | +---------------|-------------|---------------|--------------+ | main | 2 Reviewers | Required | Release Manager only. No direct pushes. | | development | N/A | Required | Only accepts merges from release/* or main. | | release/* | 1-2 Reviewers | Required | Prevents force pushes. Source of truth for the next version. |

Automation & Settings

  • Linear History: Encouraged for main to keep the production log clean.
  • Target Branch Validation: Use GitHub Actions to fail any PR that attempts to target main directly from a feature branch.
  • Auto-Sync: Configure an action to merge main back into development whenever a release is tagged.
  • Auto Updates: Configure an action to ensure the Changelog is updated.

1. Workflows

Gatekeeper

Copy [branch-gatekeeper.yml](./workflow/branch-gatekeeper.yml) to the .github/workflows/branch-gatekeeper.yml.

It ensures that only the release/ branches can target main or development.

Auto-Tag & Sync Workflow

Copy [post-release.yml](./workflow/post-release.yml) to .github/workflows/post-release.yml.

This automates the "Cleanup & Sync" phase by tagging the release and updating the development branch once the Release Manager merges to main.

This will also update the CHANGELOG.md file.

2. Templates

Copy [pull_request_template.md](./templates/pull_request_template.md) to .github/pull_request_template.md.

Since post-release.yml uses commit messages to build the changelog, adopting Conventional Commits will help with properly documenting changes.

Naming PRs like this will create a "pretty print" changelog and group features and fixes together:

  • feat: add user profile editing
  • fix: resolve memory leak in dashboard
  • docs: update installation guide

3. Repository Settings

Configure your GitHub settings:

  1. Go to Settings > Branches > Add Branch Protection Rule.

  2. For main and development:

Check "Require status checks to pass before merging".

Search for and select "enforce-strategy" (the name of the job in the YAML file).

This prevents the "Merge" button from being clickable if the Gatekeeper fails.

  1. For main only:

Enable "Restrict pushes" to only allow Release Managers/Admins.

4. Changelogs

The updates to CHANGELOG.md are automated via Post-Release Sync workflow. This automation looks at the PR titles merged into the release branch and append them to the changelog before tagging.

2. How it works

  1. Extraction: It pulls the version number directly from your release/1.2.3 branch name.
  2. Log Generation: It identifies every commit that happened since the last production release.
  3. Prepending: It places the newest release at the top of the file (standard practice) rather than the bottom, so users don't have to scroll to see what's new.
  4. Verification: Because this runs after the merge to main, the CHANGELOG.md update becomes part of the official main history and is immediately synced back to development.

3. Pro-Tip for Developers

For the changelog to look clean, encourage your team to use descriptive PR titles.

  • Instead of: fixed the bug
  • Use: fix: resolved login timeout on mobile devices (#102)

5. Summary

  • Developers can only merge feature/* or fix/* into release/*.
  • Release Managers are the only ones who can move release/* into development (for QA) and finally into main.
  • Automation handles the tagging and making sure development doesn't fall behind main.
Step Action Responsibility
1. Kickoff Create release/X.Y.Z from main. Release Manager
2. Build Feature branches merge into release/X.Y.Z. Developers & Senior Devs
3. Test Merge release/X.Y.Z into development. Release Manager
4. Deploy Merge release/X.Y.Z into main. Release Manager
5. Cleanup Automation tags vX.Y.Z, updates Changelog, and syncs development. GitHub Actions

Note: If the Auto-Sync fails due to a merge conflict, the Release Manager must manually resolve the conflict on the development branch to keep it in sync with main.