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
  1. One-time setup
    1. 1. RubyGems account and owners
    2. 2. Register a pending trusted publisher
    3. 3. Create the GitHub environment
    4. 4. Check the name is accepted
  2. Releasing a version
  3. Rehearsal
  4. Docs
  5. If something goes wrong

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:

  1. 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.
  2. 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

  1. Pick the version in lib/messengerr/version.rb (semantic versioning). While the version is 0.x, breaking changes may land in a minor release.
  2. Date the changelog. In CHANGELOG.md the heading for the version must read ## X.Y.Z (YYYY-MM-DD). A heading that still says unreleased blocks the release.
  3. Check locally:

    bundle exec rspec
    bundle exec rubocop
    bundle exec rake docs:check
    bundle exec rake release:check TAG=vX.Y.Z
    
  4. Look inside the gem. It should hold only lib/, exe/, README.md and LICENSE:

    gem build messengerr.gemspec
    tar -xOf messengerr-X.Y.Z.gem data.tar.gz | tar -tz
    
  5. Merge to main and wait for CI to pass on all of Ruby 3.2, 3.3 and 3.4.
  6. Tag the commit on main and push the tag. The workflow refuses a tag whose commit is not on main. This is the step that publishes:

    git tag vX.Y.Z
    git push origin vX.Y.Z
    
  7. Approve. The Release workflow runs verify (tag is on main, tag matches the version, changelog is dated, specs, lint, docs check), then waits for a reviewer on the rubygems environment, then publishes to RubyGems and creates a GitHub release from the changelog notes.
  8. 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.Z and git 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.

Back to top

Maintained by Daiwick. Released under the MIT License.