Release Workflow

Version 1.6.9 | Updated: September 04, 2026

Release Workflow

Status: agreed target model (DEV-1872, 2026-07-23). Trunk-based. The tooling (misc/release.sh) and CLAUDE.md still describe the previous version-branch-development flow and must be updated to match — see Tooling to update.

Branching model

  • main — the trunk. Always releasable, the single source of truth. Every feature and every fix lands here first (directly, or by cherry-pick from a release line). Nothing is “done” until it is on main.

  • Feature branches — cut from main, named feature/<DEV-xxxx>-<slug>, merged back to main via PR. A feature may add or change documentation; its docs build with the branch (preview) and land in main’s docs on merge.

  • Version / release branches (e.g. 1.6.8) — cut from main for a release. They receive stabilization and hotfixes only, not net-new feature work. QA installs a specific line with --branch 1.6.8.

  • Older versions — a fix or feature needed on an older released line is authored on that line, then cherry-picked to main and forward to any newer still-active lines. Never merge an older branch forward wholesale — a full merge drags stale code onto the newer line.

Workflow diagram

gitGraph
   commit
   branch feature
   commit
   commit
   checkout main
   merge feature
   commit
   branch release
   commit id: "stabilize"
   commit id: "v1.6.8" tag: "1.6.8"
   commit id: "hotfix"
   checkout main
   cherry-pick id: "hotfix"
   commit
  • feature is cut from main and merged back via PR.

  • release (a version branch, e.g. 1.6.8) is cut from main, takes stabilization + hotfixes only, and is tagged for the release.

  • a hotfix made on release is cherry-picked back to main (and forward to any newer active line) — never merged up.

  • backports for an older line follow the same shape: authored on that line, cherry-picked to main and to newer lines.

  • docs follow the branch: main → latest/dev, each release → /<version>/, a feature branch → a preview build for its new/changed docs.

Rules

  • Cherry-pick, don’t merge up. A fix reaches every active line by cherry-pick, never by merging an older branch into a newer one.

  • Backport vs. new feature. New features branch from main. Backports are authored where they are needed and cherry-picked to main and newer lines.

  • Keep few live version branches. Only the next release plus genuinely customer-supported lines stay active; older versions are frozen (hotfix-only) per the support window. Fewer live lines = fewer forward-ports.

  • A fix must reach main. A version branch cannot be released or closed while any of its fixes are missing from main — enforced by CI; forward-port PRs are opened automatically.

  • Hotfix SLA. Security / critical fixes propagate to all active customer lines and main within the agreed window.

Documentation

  • Each version publishes its own versioned docs (Antora, docs-friendly-tech.pages.dev/grafana-monitoring/<version>/).

  • main publishes the latest / dev docs.

  • Feature branches that add or change docs get a docs build (preview) so the new content is reviewable before merge. On merge the docs go to main’s docs, and into a version’s docs when a release branch carries the change.

  • VERSION and docs/antora.yml are per-branch and kept in sync (pre-commit version check).

Interactive installer gate

The install command in our own docs is curl … | sudo bash -s, and the installer draws a menu over it. That path has broken in ways no unit test saw: a black screen on MobaXterm under sudo, and a run that hung forever waiting for a keypress on a /dev/tty nobody was watching.

Before tagging a release, work through interactive-release-checklist.md. It has four parts and all four are required:

  1. The automated Phase 1 suite — bash misc/testing/interactive/run-phase1.sh, mirrored in CI by the interactive job in .github/workflows/sandbox-tests.yml. Compare against the absolute counts recorded in the checklist, not only against FAILED STAGES: 0: every gate asserts “at or above a floor”, which a suite that quietly shrank still clears.

  2. Mutation coverage — bash misc/testing/scripts/check-red-verify.sh plus a scoped red-verify.sh sweep. A suite where every test passes proves nothing until the tests have been watched to fail against the defects they guard; that is the whole reason this phase exists.

  3. A manual client matrix — OpenSSH, Windows Terminal, MobaXterm and PuTTY / a web console. The automated suites run on terminals we control and cannot speak for the clients customers actually use.

  4. Acknowledgement of the known open defect: Ctrl-C at the config menu does not restore the terminal. Phase 1 reproduces it and neither state fails CI, so a release must not be signed off assuming it is fixed.

Three prerequisites are easy to miss and silent when absent, so section 0 of the checklist covers them: the pre-commit gate does not exist until bash misc/install-hooks.sh --yes has been run (once per clone — in a worktree the hook lives in the shared git directory and covers every worktree); tmux must be installed on every runner carrying the ft-ci label, because the interactive job’s rendering suite refuses to skip under CI; and a Docker daemon must be running on the machine you sign off from, unless promtool is installed locally. Without either, validate-all’s Test 41 fails with failed to connect to the docker API, and step 2’s red-verify.sh sweeps abort with exit 65 and the baseline run is not a usable reference — a red baseline, not a broken gate.

The agent-facing version of the same rule — which test to update when you touch TTY detection, /dev/tty, screen/cursor handling or the sourced UI — is in AGENTS.md at the repository root.

Releasing

./misc/release.sh           # patch bump (1.6.8 → 1.6.9)
./misc/release.sh minor     # minor bump (1.6.8 → 1.7.0)
./misc/release.sh major     # major bump (1.6.8 → 2.0.0)

The bump names the next development branch, not the release: the version being released is whatever VERSION already says.

The released branch is kept. It used to be deleted once merged and tagged, on the reasoning that the line was finished. It is not: the branch is what QA installs with --branch, what a customer’s stand is pinned to, and what a support question three months later is about. A tag answers “what was released”; the branch answers “what is a stand running”. Pass --delete-branch to opt into the old behaviour:

./misc/release.sh minor --delete-branch

Requirements

  • No uncommitted changes.

  • GitHub CLI (gh) installed and authenticated.

The script’s current behaviour still assumes the previous model (see below). Treat this section as the intended release entry point; the script itself is pending adaptation.

Tooling to update

Follow-ups to make the tooling match this model (DEV-1872 automation; ties into DEV-1916 CI/CD, which adds build → scan → publish → deploy stages the flow must accommodate):

  • misc/release.sh — today it must run from a version branch, merges the branch into main, deletes it, creates the next version branch, and continues development there (the version-branch-dev model). Under trunk-based it should instead cut/tag a release branch from main and leave development on main. Needs rework.

  • CLAUDE.md — the note “Development happens on version branches; main only receives merges at release time” must be updated to the trunk-based model.

  • CI — add the “fix is on main” gate before a version branch can be released, plus automatic forward-port PRs from an older line to newer ones.

  • Docs pipeline — add a per-feature-branch docs preview build so new or changed documentation is reviewable before merge.

Bootstrap commands

  • …​ | bash -s — <ip> — latest release from main

  • …​ | bash -s — --branch 1.6.8 <ip> — specific line (dev / release branch)

  • …​ | bash -s — --version-list — show all versions

--version-list output

Available versions:

  Released:
    1.6.8 (latest)
    1.6.7
    1.6.6
    ...

  In development:
    (current release branch)

Files updated on release

  • VERSION — new version number

  • docs/antora.yml — version: 'X.Y.Z'

  • docs/modules/ROOT/pages/*.adoc — :revnumber:, version line, date

Troubleshooting

“Uncommitted changes detected”

Commit or stash first:

git add -A && git commit -m "fix: something"
# or
git stash

“GitHub CLI not authenticated”

gh auth login

tag 1.6.9 · commit a4c0a5e133c2cba0a8b461039e9634af33e3dd9b · page generated September 04, 2026