Merge pull request #18 from meticulous/claude/release-bundler-fix #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release to RubyGems | |
| # Triggers on tag pushes matching `vX.Y.Z`. The release flow expects: | |
| # (1) version bump committed and merged to main, (2) tag `vX.Y.Z` | |
| # created against the merge commit (we use annotated tags by | |
| # convention: `git tag -a vX.Y.Z -m '…'`), (3) tag pushed. | |
| # | |
| # Once the trusted publisher is configured on rubygems.org (see | |
| # doc/PUBLISHING.md), no API key or secret is needed — RubyGems | |
| # authenticates via the GitHub OIDC token this job mints. | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| # Security note: no untrusted user input (issue titles, PR bodies, | |
| # comment text) is interpolated into any `run:` block. The only | |
| # externally-driven value is GITHUB_REF_NAME (used below to derive | |
| # the tag name) — controlled by whoever pushed the tag, which is | |
| # constrained to maintainers with repo write access AND further | |
| # constrained by the `tags: ['v*']` filter on the trigger defined | |
| # above. Third-party actions are pinned to commit SHAs to reduce | |
| # supply-chain risk if a floating tag is moved or compromised; | |
| # rotate during routine maintenance. | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| # `release` is the conventional environment name RubyGems' pending | |
| # trusted publisher form suggests. Using the convention so the | |
| # rubygems.org setup form's defaults match what the workflow does. | |
| environment: | |
| name: release | |
| url: https://rubygems.org/gems/guardrails | |
| # `id-token: write` is the critical permission for trusted | |
| # publishing — the action mints a GitHub OIDC token RubyGems | |
| # exchanges for a short-lived API key. `contents: read` is the | |
| # minimum needed for checkout. No `contents: write` because we | |
| # don't write back to the repo; tagging is a manual prereq. | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1 branch head as of 2026-05-11 | |
| with: | |
| ruby-version: "3.2" | |
| # Ruby 3.2.11 ships with bundler 2.4.19, which doesn't handle | |
| # the `securerandom` default-gem conflict that surfaces when a | |
| # transitive dep requires a newer securerandom than the one | |
| # the stdlib ships. `bundler: latest` resolves it (>= 2.5). | |
| # The v1.0.0 first-publish run caught this — see PR #18. | |
| bundler: latest | |
| bundler-cache: true | |
| # Belt-and-braces: refuse to publish a tag whose version doesn't | |
| # match `Guardrails::VERSION` (which becomes `spec.version` via | |
| # the gemspec). Without this, a stray `git tag v1.0.1` against a | |
| # `1.0.0` lib/guardrails/version.rb would publish the wrong | |
| # artifact to a slot you can never re-use (yanked versions can't | |
| # be republished under the same number). Runs before tests so | |
| # the failure mode is fast. | |
| # | |
| # GITHUB_REF_NAME is the tag name without the `refs/tags/` prefix | |
| # — tag-pusher-controlled but constrained to maintainers per the | |
| # trigger filter. | |
| - name: Verify Guardrails::VERSION matches tag | |
| run: | | |
| GEM_VERSION="$(ruby -Ilib -e 'require "guardrails/version"; puts Guardrails::VERSION')" | |
| TAG="${GITHUB_REF_NAME#v}" | |
| if [ "$GEM_VERSION" != "$TAG" ]; then | |
| echo "::error::Guardrails::VERSION ($GEM_VERSION) does not match tag (v$TAG). Refusing to publish." | |
| exit 1 | |
| fi | |
| echo "Releasing guardrails $GEM_VERSION (tag v$TAG)" | |
| - name: Run the test suite | |
| run: bundle exec rspec | |
| # Official RubyGems trusted-publisher action. Exchanges the | |
| # GitHub OIDC token for a short-lived RubyGems API key, builds | |
| # the gem, and pushes. Action infers the gemspec from the repo | |
| # root and only pushes if rubygems.org accepts the OIDC claim | |
| # against a registered (or pending) trusted publisher. | |
| - name: Build and push to RubyGems.org | |
| uses: rubygems/release-gem@6317d8d1f7e28c24d28f6eff169ea854948bd9f7 # v1.2.0 |