Imported from ruby-git/ruby-git (
.github/skills/release-management/SKILL.md). Install upstream withnpx skills add ruby-git/ruby-git --skill release-management. Copyright stays with the author.
Release Management Workflow
This workflow describes how releases are managed for the ruby-git gem.
Contents
- How to use this skill
- Related skills
- How Releases Work
- Developer Responsibilities
- Checking Release Readiness
- Cutting a maintenance branch
- Major release readiness
- After a major release
- What NOT to Do
- Useful Commands
How to use this skill
Attach this file to your Copilot Chat context when preparing a release, verifying release readiness, or answering questions about versioning and publishing flow.
Related skills
- Dependency Management — dependency updates that affect release content and risk
- PR Readiness Review — ensure changes are release-ready before merge
- Breaking Change Analysis — evaluate and communicate major-version impact
How Releases Work
Releases are fully automated via
release-please and the
.github/workflows/release.yml workflow:
- Developers merge PRs with conventional commit messages into a release
branch:
mainfor the next major, or a maintenance branch such as5.xor4.xfor a patch or minor release of an earlier series - release-please automatically opens (and keeps updated) a release PR that
bumps
lib/git/version.rband regeneratesCHANGELOG.md - When a maintainer merges the release PR, release-please creates a GitHub release with a tag
- The workflow then publishes the gem to RubyGems.org via
rubygems/release-gem
Key config files:
| File | Purpose |
|---|---|
.release-please-config.json |
Release-please settings (release type, changelog sections, versioning strategy) |
.release-please-manifest.json |
Tracks the current released version |
lib/git/version.rb |
Version constant (updated automatically by release-please) |
CHANGELOG.md |
Release history (updated automatically by release-please) |
prerelease is false, so release-please never proposes a beta and every release is
a normal release. The config also sets bump-minor-pre-major: true and
bump-patch-for-minor-pre-major: true, which affect version bumps only while the major
version is 0.
Developer Responsibilities
The only thing developers need to do for releases is use conventional commit messages. release-please determines the version bump from commit types:
fix:→ patch bumpfeat:→ minor bumpfeat!:orBREAKING CHANGE:footer → major bump
Everything else (version bump, changelog, tag, gem push) is automated. Do not
manually edit lib/git/version.rb or CHANGELOG.md.
Checking Release Readiness
Before a maintainer merges a release PR:
-
Ensure CI passes on the release branch (
main,5.x, or4.x):bundle exec rake default -
Review unreleased changes since last tag:
git log $(git describe --tags --abbrev=0)..HEAD --oneline -
Check for open blockers:
gh issue list --label "bug" --state open -
Review the release PR — verify the auto-generated changelog and version bump look correct.
-
Retire the release banner — if
README.mdopens with a banner announcing this major's.0.0release and the release PR is the major's first minor, merge a docs PR that removes the banner before merging the release PR. The banner announces the major; once the series has a minor, the dated announcement entry carries the history.
Cutting a maintenance branch
main becomes the release line for the next major as soon as the first removal merges
(ADR-0007),
which can be long before that major ships. Cut the maintenance branch for the current
major at that point, not after the major release, so the series can keep releasing
while main is pinned to the next major.
The cut is two pull requests, one into each branch, because each branch runs its own
copy of the workflows. Both carry the same docs commit: write it once, cherry-pick it
onto the other branch, and cherry-pick it again whenever review changes it on either
side, so the two branches say the same thing. Merge the main PR first so the pin is
in place before anything else lands on main. Below, <N> is the major being cut,
<N+1> the major main will release next, and <M> the major of the maintenance
branch that already exists.
On main:
- Add a README announcement entry dated the cut day: every further v.x release
comes from the new branch, and the next release from
mainis v<N+1>.0.0. - Put a development note at the top of
README.md, replacing the release banner if one is still there:mainis unreleased v<N+1>.0.0 development, the current release series is v.x, released from the new branch, and the "Upgrading to v<N+1>.x" section ofUPGRADING.mdsays what changes. Name the series, not a tag: later v.x releases do not touchmain, so a tag in the note would go stale. This goes on amain-only commit, never on the shared docs commit: the new branch keeps whateverREADME.mdopened with at the branch point. - Pin the next release from
mainto the next major with aRelease-As: <N+1>.0.0footer on the announcement commit. Without the pin, the first commit merged tomainafter the cut has release-please open a release PR for the next v patch or minor frommain, colliding with the release stream on the new branch. release-please reads the footer from any commit since the last tag, so the pin holds until the major ships and then expires on its own. The footer goes on amain-only commit and never on the shared docs commit, which is cherry-picked onto the new branch and would pin that branch's next release to the major too. Do not use therelease-askey in.release-please-config.jsoninstead: it applies to every release PR until someone remembers to remove it.
On the new branch:
- Create the branch
<N>.xfrom the latest tag of that major and protect it with a ruleset namedRelease Branch (<N>.x), copied fromRelease Branch (default). The copy requires the same status checks asmain. Until the next item lands, the only PR that can satisfy them is that item's own, whose head carries the triggers. - Add the branch to the
pushtrigger and the release job guard inrelease.yml, to thepull_requesttriggers incontinuous_integration.ymlandenforce_conventional_commits.yml, and to thepushtrigger inwarm_bundler_caches.yml, all under.github/workflows/. The workflow that runs is the one on the branch pushed to or targeted, and a Bundler cache is readable only from the ref that wrote it, its base ref, and the default branch, so the copies onmainneed no change. - Expect release-please to open a release PR from the new branch as soon as this
PR merges. No commit type is hidden in
.release-please-config.json, so the workflow and docs commits alone propose the next patch. Leave that release PR open until the series has something worth releasing, or merge it.
On both, in the shared docs commit:
- Name the new branch beside the existing maintenance branch everywhere that one is
listed: the branch tables in
.github/copilot-instructions.mdandCONTRIBUTING.md, the release support policy inREADME.md, the protected branch list in.husky/pre-commit, and the skills that list the protected branches.grep -rn '<M>\.x' .github .husky CONTRIBUTING.md README.md, with the existing maintenance branch's major in place of<M>, finds them all.
Major release readiness
Before merging the release PR for a major version, run Checking Release Readiness, then confirm each item below. The per-PR removal gate lives in Breaking Change Analysis, Step 4 and is checked when each removal PR merges, not here.
- Version floors are updated everywhere they are set:
required_ruby_versioningit.gemspec,TargetRubyVersionin.rubocop.yml, the CI workflow matrices under.github/workflows/,Git::MINIMUM_GIT_VERSIONinlib/git.rb, the README "Ruby version support policy" and "Git version support policy" subsections, and the Compatibility list in Project Context. Include any RuboCop cleanup aTargetRubyVersionbump triggers. - ADR-0004 audit: the options the new git floor kills are deprecated in this major (ADR-0004).
- Carried deprecations, if any, have their warning text,
@deprecatedYARD tag, andUPGRADING.mdentry updated to name the major the roadmap decided for them, or "a future major release" while that is undecided, and the horizon passed toActiveSupport::Deprecation.newinlib/git.rbis bumped to the next major. - The "Upgrading to vN.0.0" section of
UPGRADING.mdis complete. - README examples use no removed APIs.
- The changelog preview in the release PR reads correctly and every removal commit
carries a
BREAKING CHANGEfooter. - The development note at the top of
README.mdis replaced with a release banner naming the new major and linking toUPGRADING.mdandCHANGELOG.md, in a docs PR merged before the release PR.README.mdships in the gem and on RubyDoc, so a banner added after the release never reaches the major's own artifact. The major's first minor release removes the banner; see Checking Release Readiness.
After a major release
- Add a README announcement entry dated the release day.
- Support for the oldest maintenance branch ends with this release (see the release
support policy in
README.md). Retire it everywhere it is named. In the workflow triggers and release job guard under.github/workflows/, replace it with the newer maintenance branch, which the cutting step left out of the copies onmain. Everywhere else the newer branch is already listed, so remove the retired one: the branch tables in.github/copilot-instructions.mdandCONTRIBUTING.md, the release support policy inREADME.md, the protected branch list in.husky/pre-commit, and the skills that list the protected branches.grep -rn '<M>\.x' .github .husky CONTRIBUTING.md README.md, with the retired branch's major in place of<M>, finds them all. - Close the milestone and update the roadmap issue.
What NOT to Do
- Do not manually bump
lib/git/version.rb— release-please does this - Do not manually edit
CHANGELOG.md— it is auto-generated from commits - Do not manually create tags — release-please creates them on merge
- Do not manually
gem push— the workflow handles publishing - Do not force-push or rebase the release PR — release-please manages it
Useful Commands
# View recent tags
git tag -l --sort=-v:refname | head -10
# List commits since last release
git log $(git describe --tags --abbrev=0)..HEAD --oneline
# Compare with previous release
git diff $(git describe --tags --abbrev=0)..HEAD
# Check current version
ruby -e "require_relative 'lib/git/version'; puts Git::VERSION"
# View release-please config
cat .release-please-config.json | jq .
# Build gem locally (for testing only)
bundle exec rake build
gem install pkg/git-*.gem