From aa21ed2dd140e060831a0f8fd6e0536451636a98 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 1 Oct 2026 01:47:18 +0200 Subject: [PATCH] THRIFT-6395: Fix the Ruby gem release workflow and limit it to release tags Client: rb The workflow has never published a gem. Its release-gem step runs "bundle exec rake release", but the job does not install the bundle, since THRIFT-5965 turned bundler-cache off. Replayed in ruby:4.0 with Bundler 2.2.34, it fails with Bundler::GemNotFound. A step now installs the bundle, frozen to Gemfile.lock. It does not go through bundler-cache, because a job that publishes should not restore a cache. With the bundle installed, Bundler's release task would create and push the version tag if it does not exist yet, and then publish. The workflow can be started by hand from any branch, so a run from master would push a v0.26.0 tag and publish 0.26.0. The job now checks that it runs for a release tag matching the gemspec version, as release_rust.yml does for the crate, and it gets contents: read, so it cannot push a tag at all. Pre-releases are skipped, as in the other publishing workflows. doc/ReleaseManagement.md gets an entry for the workflow. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/release_ruby.yml | 40 +++++++++++++++++++++++++++++- doc/ReleaseManagement.md | 12 +++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release_ruby.yml b/.github/workflows/release_ruby.yml index 9048cc66ba1..e6dfad80081 100644 --- a/.github/workflows/release_ruby.yml +++ b/.github/workflows/release_ruby.yml @@ -26,10 +26,16 @@ on: jobs: publish: + # Never for a pre-release, like pypi.yml and release_rust.yml. + if: ${{ github.event_name != 'release' || !github.event.release.prerelease }} runs-on: ubuntu-latest permissions: - contents: write + # Read only on purpose. Bundler's release task creates and pushes the + # version tag if it does not exist yet, and release tags are for the + # release manager to create. The version check below makes sure it + # always exists. + contents: read id-token: write environment: release @@ -46,6 +52,38 @@ jobs: ruby-version: "4.0" working-directory: lib/rb + # Started from a branch, the release task would tag and publish whatever + # version the branch has. Only a release tag that matches the gemspec + # gets past this step. + - name: Verify the gem version matches the release tag + working-directory: lib/rb + env: + REF: ${{ github.ref }} + run: | + case "$REF" in + refs/tags/v*) TAG_VERSION="${REF#refs/tags/v}" ;; + *) + echo "::error::$REF is not a release tag. Run this workflow from the release tag, for example v1.0.0." + exit 1 + ;; + esac + GEM_VERSION=$(ruby -e 'print Gem::Specification.load("thrift.gemspec").version') + if [ "$GEM_VERSION" != "$TAG_VERSION" ]; then + echo "::error::Version mismatch: thrift.gemspec=$GEM_VERSION, tag=v$TAG_VERSION" + exit 1 + fi + echo "Version check passed: $GEM_VERSION" + + # The release task runs through "bundle exec", so the bundle has to be + # installed. Not with bundler-cache above: a job that publishes should + # not restore a cache that another workflow run could have written. + - name: Install the bundle + working-directory: lib/rb + env: + # Exactly what Gemfile.lock records, or fail. + BUNDLE_FROZEN: "true" + run: bundle install + # Release - uses: rubygems/release-gem@052cc82692552de3ef2b81fd670e41d13cba8092 # v1.4.0 with: diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md index 4d985ca26fc..48e4e00242a 100644 --- a/doc/ReleaseManagement.md +++ b/doc/ReleaseManagement.md @@ -622,6 +622,18 @@ See https://thrift.apache.org/lib/ for the current status of each external packa * PyPI distribution filenames are immutable. If an artifact was published with the wrong contents, prepare a new Apache Thrift release rather than trying to replace the existing PyPI file. +* [ruby] The `Release Ruby Gem` GitHub Actions workflow publishes the `thrift` + gem to RubyGems.org when the GitHub release is published, using trusted + publishing. + * Before publishing, verify that the `thrift` gem on RubyGems.org has a + trusted publisher for the `apache/thrift` repository, the + `.github/workflows/release_ruby.yml` workflow and the `release` environment. + * The workflow skips pre-releases, and it publishes only from a release tag + whose version matches `lib/rb/thrift.gemspec`. To publish after a failed + run, re-run it, or start it from the Actions tab with the release tag + selected under *Use workflow from*. + * RubyGems.org takes a version only once. If a gem was published with the + wrong contents, prepare a new Apache Thrift release. * [rust] Any thrift project committer is allowed to upload a new crate. If you have any questions email `dev@thrift.apache.org`.