Releasing
This guide documents RatatuiRubyβs release workflow. We use trunk-based development with release branches.
Overview
-
trunkβ Active development. Features land here first. -
release/X.Yβ Release series branches (e.g.,release/1.0). -
stableβ Always points to the latest stable release.
trunk βββββββββββββββββββββββββββββ (future work)
\ \
release/1.0 ββββββββββ \ (1.0.0, 1.0.1, ...)
\
release/1.1 βββββββββ (1.1.0, 1.1.1, ...)
Versioning Philosophy
We follow strict SemVer without ceremony:
-
Breaking change? β Bump major
-
New feature? β Bump minor
-
Bug fix? β Bump patch
Version numbers are technical artifacts, not marketing. If we end up at v50 by yearβs end, so be it.
Changelog Management
Trunk maintains the canonical project history. Each release branch maintains its own changelog during development, then syncs back to trunk.
During Beta/RC Cycles
The release branch (release/1.0) tracks granular changes:
## [Unreleased] ## [1.0.0-beta.2] - 2026-01-20 ### Fixed - TableState row navigation methods ## [1.0.0-beta.1] - 2026-01-20 - Initial 1.0 beta release
Trunkβs [Unreleased] section accumulates features for the next minor:
## [Unreleased] ### Added - Terminal Capability Detection ### Fixed - TableState row navigation methods
The fix appears in both places. This is correct β both branches contain it.
When Final Ships
When 1.0.0 final releases, consolidate all beta entries into one section on both branches:
release/1.0: <!β SPDX-SnippetBegin β> <!β SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 β>
## [1.0.0] - 2026-xx-xx ### Fixed - TableState row navigation methods ## [0.10.3] - 2026-01-16 ...
trunk (synced): <!β SPDX-SnippetBegin β> <!β SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 β>
## [Unreleased] ### Added - Terminal Capability Detection ## [1.0.0] - 2026-xx-xx ### Fixed - TableState row navigation methods ## [0.10.3] - 2026-01-16 ...
The beta granularity served its purpose during testing. Git tags preserve the detailed history.
Release Workflows
Bugfix (Patch) Release
For bugs affecting a released version:
-
Fix on trunk first β All bugs get fixed on trunk.
-
Cherry-pick to release branch with provenance:
bash git checkout release/1.0 git cherry-pick -x <commit> # -x adds "cherry picked from" trailer -
Update the changelog on the release branch.
-
Bump and release:
bash bundle exec rake bump:patch bundle exec rake release
New Version (Major/Minor)
When trunk is ready for a new release series:
-
Decide version based on changes:
-
Breaking changes β Major (2.0.0)
-
New features only β Minor (1.1.0)
-
Create release branch:
bash git checkout trunk git checkout -b release/1.1 # or release/2.0 -
Release from the branch:
bash bundle exec rake bump:exact[1.1.0-beta.1] bundle exec rake release -
Bump trunk to the next dev version if desired.
-
Iterate through betas/RCs as needed, then ship final.
-
Sync changelog β When final ships, add the consolidated section to trunk.
Prerelease Notes
RubyGems normalizes prerelease versions. Our rake release task automatically:
-
Lets Bundler create the normalized tag (e.g.,
v1.0.0.pre.beta.1) -
Deletes it locally and remotely
-
Creates the SemVer tag (e.g.,
v1.0.0-beta.1) and pushes it
This keeps our Git tags strictly SemVer-compliant.
Commands Reference
# Bump version bundle exec rake bump:patch # 1.0.0 β 1.0.1 bundle exec rake bump:minor # 1.0.0 β 1.1.0 bundle exec rake bump:major # 1.0.0 β 2.0.0 bundle exec rake bump:exact[1.0.0-beta.1] # Release (builds, tags, pushes gem, updates stable branch) bundle exec rake release # Watch builds bin/hbs # Wait for SourceHut builds bin/hbs && bundle exec rake release # Release only if builds pass