release
Cut a release -- check main, run rake bump, watch the gem go out
SKILL.md.claude/skills/release/SKILL.md
GitHubRelease what is on main: bump the version, tag it, push, and report when
RubyGems.org has it. A release cannot be taken back, so every step looks
before it acts.
The mechanism is bundle exec rake bump (the task in the Rakefile)
followed by .github/workflows/push_gem.yml, which the tag triggers, as
the README's development section describes. Do not use bundle exec rake release: it pushes the gem from the local machine, which has no
RubyGems.org credentials here, and the tag it pushes first triggers the
workflow, which publishes the same gem through trusted publishing -- two
publishes of one version, one of which fails.
Look first. Every one of these has to hold, and the skill stops and says which does not rather than releasing around it:
git branch --show-currentismain. Releases are cut from there;rake bumpchecksmainout itself, but a switch mid-release is a surprise, not a step.git status --shortshows no tracked change.rake bumpcommits with-a, so any tracked change lying in the tree would go into the version commit; commit it (thepushskill) or set it aside. The untracked scratch files this tree habitually carries are harmless to-aand can stay.git fetch originand thengit rev-parse HEAD origin/mainagree.rake bumppulls, so a remote ahead of HEAD (a Dependabot merge is the usual case) would be released without having been looked at.CI is green for HEAD on all three test workflows:
gh run list --commit $(git rev-parse HEAD) --json workflowName,status,conclusion --jq '.[] | "\(.workflowName): \(.status) \(.conclusion)"'says
completed successforubuntu,macosandwindows. Queued or running is not green yet -- start one background wait on their conclusion, as thepushskill does, and take the release up when it lands. Red is a stop.
Know what is being released. The version is a single integer (
VERSION = "27") andrake bumpadds one, so the next version is the last tag plus one:git describe --tags --abbrev=0 git log --oneline $(git describe --tags --abbrev=0)..HEADRead the subjects, and the bodies where a subject leaves it open, and name in the report the commits the release carries. When the history since the last tag is only documentation, Dependabot bumps and housekeeping, ask whether a release is wanted at all rather than cutting one for nothing.
Bump, tag and push, which one command does:
bundle exec rake bumpIt checks out
main, pulls, rewriteslib/textbringer/version.rb, commits that one file with the subjectBump version to <N>-- the way every release commit here reads, with no trailer -- pushes, tags the commitv<N>, and pushes the tag. Check its work:git show --stat HEADnames version.rb alone,git tag --points-at HEADnames the tag, andgit ls-remote --tags origin v<N>shows it on the remote. If the task stopped partway, report exactly which of those steps happened and do not repeat it blindly: a pushed tag is already a release. Never force-push here: a tag that reached the remote is what the workflow released, and rewriting it would release something else under the same name.Watch the gem go out. The
v*tag runspush_gem.yml, which publishes through RubyGems.org's trusted publishing, creates a GitHub release with generated notes, and purges the README's image cache. Check once --gh run list --workflow push_gem.yml --limit 1-- and start one background wait on that run's conclusion:RUN=$(gh run list --workflow push_gem.yml --limit 1 --json databaseId --jq '.[0].databaseId') until gh run view $RUN --json status --jq .status | grep -q completed; do sleep 20; done gh run view $RUN --json conclusion --jq .conclusionNever poll in the foreground. When it is green, confirm the version is up with
gem search -r -e textbringer. A red run means the tag is on the remote and the gem may not be on RubyGems.org; report the failed step's log (gh run view $RUN --log-failed), and leave the tag where it is -- the fix is a new release, not a moved tag.Report: the version, the range the release covers (
v<previous>..v<new>) with the commits that decided it, the workflow's conclusion once it arrives with https://rubygems.org/gems/textbringer, and the GitHub release (gh release view v<N> --json url --jq .url). Nothing else needs updating for a release: neither README carries a version number, and the gemspec reads it from version.rb.