Releasing
Pushing a version tag publishes the gem to RubyGems through GitHub Actions. Nothing is stored in the repository that could publish it: the release job proves its identity to RubyGems with a short-lived token (trusted publishing).
On this page
A published version can never be replaced or reused. If something is wrong you can only yank it and publish a new version. Check everything before you push the tag.
One-time setup
Do this once, before the first release. It needs people with the right access, so it cannot be done from the repository alone.
1. RubyGems account and owners
A GitHub organisation cannot own a gem. RubyGems ownership belongs to user accounts, so the organisation is represented by accounts:
- The first owner is a maintainer’s own RubyGems account. It registers the trusted publisher in the next step, and becomes the gem’s owner on the first release. Make sure that account has multi-factor authentication set to UI and API (the gem requires MFA to publish:
rubygems_mfa_required), a second device registered, and its recovery codes saved. - Add named teammates as owners right after the first release (
gem owner messengerr --add EMAIL, or the gem’s Ownership page), each with their own MFA. Two or more owners means no single account is the only way to manage the gem. Ownership can later move to a shared Daiwick account or an organisation without republishing the gem.
Releases are published by the workflow, not by anyone’s login, so owner accounts are only needed for administration.
RubyGems Organizations. RubyGems has an Organizations feature with owner, admin and maintainer roles. As of early 2026 it is in private beta: teams apply through the interest form in the announcement.
2. Register a pending trusted publisher
Because the gem does not exist yet, register a pending publisher so the first release can also be done without an API key. On RubyGems.org open your profile, then Trusted publishers, add a pending publisher with:
| Field | Value |
|---|---|
| Gem name | messengerr |
| Repository owner | Jalappeno-apps (exactly as GitHub shows it) |
| Repository name | messengerr |
| Workflow filename | release.yml |
| Environment | rubygems |
After the first successful release the pending entry becomes a normal trusted publisher for the gem. See RubyGems’ guide to pushing a new gem.
3. Create the GitHub environment
In the repository, Settings, Environments, create an environment named rubygems (it must match the value above). Add required reviewers so a person has to approve each release before the publish job runs. Use Prevent self-review only if you have at least two reviewers.
On GitHub Free, environments (and their reviewers) only work for public repositories. If the repository is private on a Free plan, the approval gate is ignored, so check the repository’s visibility before relying on it.
4. Check the name is accepted
The name messengerr is currently free on RubyGems, but a different gem named messenger exists and RubyGems applies name-similarity checks that can only be tested by publishing. If the first push is rejected for the name, nothing is published and no version is used up. Choose another name then (it touches the gemspec, the CLI executable, the docs and the URLs).
Releasing a version
- Pick the version in
lib/messengerr/version.rb(semantic versioning). While the version is0.x, breaking changes may land in a minor release. - Date the changelog. In
CHANGELOG.mdthe heading for the version must read## X.Y.Z (YYYY-MM-DD). A heading that still saysunreleasedblocks the release. -
Check locally:
bundle exec rspec bundle exec rubocop bundle exec rake docs:check bundle exec rake release:check TAG=vX.Y.Z -
Look inside the gem. It should hold only
lib/,exe/,README.mdandLICENSE:gem build messengerr.gemspec tar -xOf messengerr-X.Y.Z.gem data.tar.gz | tar -tz - Merge to
mainand wait for CI to pass on all of Ruby 3.2, 3.3 and 3.4. -
Tag the commit on
mainand push the tag. The workflow refuses a tag whose commit is not onmain. This is the step that publishes:git tag vX.Y.Z git push origin vX.Y.Z - Approve. The Release workflow runs
verify(tag is onmain, tag matches the version, changelog is dated, specs, lint, docs check), then waits for a reviewer on therubygemsenvironment, then publishes to RubyGems and creates a GitHub release from the changelog notes. -
Confirm. Check the gem page on RubyGems, then install it in a clean directory:
gem install messengerr -v X.Y.Z messengerr --version
Do not run rake release yourself unless you mean to publish: it tags and pushes the gem straight away. The workflow runs it for you.
Rehearsal
Before the first real release, check the workflow with a tag that is meant to fail:
git tag v0.0.0-rehearsal
git push origin v0.0.0-rehearsal
The verify job should run and stop at “tag does not match the gem version”, so publish never starts and nothing can reach RubyGems. Then delete the tag:
git push origin :refs/tags/v0.0.0-rehearsal
git tag -d v0.0.0-rehearsal
Docs
The docs site is separate from the gem. It redeploys to GitHub Pages whenever docs/** changes on main, and needs no release.
If something goes wrong
- The workflow fails in
verify. Nothing was published. Fix the problem, then move the tag: delete it (git tag -d vX.Y.Zandgit push origin :refs/tags/vX.Y.Z), commit the fix, and tag again. - The workflow fails after publishing. Check RubyGems before retrying. If the version is there, do not publish it again: only the GitHub release is missing, and you can create it by hand.
-
A bad version was published. Yank it so new installs skip it, then publish a fixed version:
gem yank messengerr -v X.Y.Z - A credential or secret was published inside the gem. Yank it, rotate the secret, and publish a clean version. Yanking does not remove copies people already downloaded.