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`.