| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| name: Release Ruby Binding |
| |
| on: |
| push: |
| tags: |
| # Triggers on version tags (v0.54.0, v0.54.0-rc.1, etc.) |
| - "v[0-9]+.[0-9]+.[0-9]+" |
| - "v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+" |
| pull_request: |
| branches: |
| - main |
| paths: |
| - ".github/workflows/release_ruby.yml" |
| workflow_dispatch: # allow repo collaborators to publish gem |
| |
| concurrency: |
| group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} |
| cancel-in-progress: true |
| |
| permissions: |
| contents: read |
| id-token: write # required for workflow to publish gem if releasing |
| |
| defaults: |
| run: |
| working-directory: bindings/ruby |
| |
| jobs: |
| build: |
| runs-on: ubuntu-latest |
| outputs: |
| version: ${{ steps.summary.outputs.version }} |
| |
| steps: |
| - name: Checkout repository |
| uses: actions/checkout@v5 |
| |
| - name: Setup Ruby |
| uses: ruby/setup-ruby@v1 |
| with: |
| bundler-cache: true |
| working-directory: bindings/ruby |
| |
| - name: Build source gem (Ruby-only) |
| run: bundle exec rake build |
| |
| - name: Show built gems |
| run: ls -la pkg/ |
| |
| - name: Upload artifact (source gem) |
| uses: actions/upload-artifact@v4 |
| with: |
| name: opendal-ruby-gem-source |
| path: bindings/ruby/pkg/*.gem |
| retention-days: 30 |
| |
| - name: Log Build Summary |
| id: summary |
| run: | |
| # e.g. from `Cargo.toml` to released version: |
| # - 0.54.0 -> 0.54.0 |
| # - 0.54.0-rc.1 -> 0.54.1.pre.rc.1 |
| VERSION=$(bundle exec rake version) |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" |
| |
| echo "## Ruby gem built successfully! 📦" >> "$GITHUB_STEP_SUMMARY" |
| echo "" >> "$GITHUB_STEP_SUMMARY" |
| echo "**Ref:** ${{ github.ref_name || github.ref }}" >> "$GITHUB_STEP_SUMMARY" |
| echo "**Version:** $VERSION" >> "$GITHUB_STEP_SUMMARY" |
| |
| # We maintain multiple build targets for native gems. |
| # We only provide best-effort support for native gems. We could withdraw the support to these builds at any time. |
| build-native: |
| strategy: |
| fail-fast: false |
| matrix: |
| include: |
| - os: ubuntu-latest |
| platform: x86_64-linux |
| rust_target: x86_64-unknown-linux-gnu |
| - os: ubuntu-24.04-arm |
| platform: aarch64-linux |
| rust_target: aarch64-unknown-linux-gnu |
| - os: macos-latest |
| platform: arm64-darwin23 |
| rust_target: aarch64-apple-darwin |
| |
| runs-on: ${{ matrix.os }} |
| continue-on-error: true |
| |
| env: |
| RB_SYS_CARGO_TARGET: ${{ matrix.rust_target }} |
| |
| steps: |
| - name: Checkout repository |
| uses: actions/checkout@v5 |
| |
| - uses: dtolnay/rust-toolchain@stable |
| with: |
| targets: ${{ matrix.rust_target }} |
| |
| - name: Setup Ruby and install dependencies |
| uses: ruby/setup-ruby@v1 |
| with: |
| bundler-cache: true |
| working-directory: bindings/ruby # must repeat because GitHub Actions will not use defaults.run |
| |
| - name: Show available rake tasks |
| run: bundle exec rake --tasks |
| |
| - name: Build native gem |
| run: bundle exec rake native:opendal:${{ matrix.platform }} gem |
| |
| - name: Collect built gem |
| run: | |
| echo "Built gem file:" |
| ls -la pkg/ |
| echo "" |
| |
| mkdir -p pkg_out |
| cp -r pkg/*.gem pkg_out/ |
| |
| - name: Upload gem artifact |
| uses: actions/upload-artifact@v4 |
| with: |
| name: opendal-ruby-gem-${{ matrix.platform }} |
| path: bindings/ruby/pkg_out/*.gem |
| retention-days: 30 |
| |
| publish: |
| # allow: |
| # - standard tag releases |
| # - workflow_dispatch: |
| # - reattempt standard tag releases |
| # - pre-releases |
| |
| # if: >- |
| # startsWith(github.ref, 'refs/tags/v') || |
| # (github.event_name == 'workflow_dispatch' && contains(needs.build.outputs.version, 'rc')) |
| |
| # Don't start publish until we are ready |
| if: false |
| needs: [build, build-native] |
| runs-on: ubuntu-latest |
| |
| steps: |
| - name: Checkout repository |
| uses: actions/checkout@v5 |
| with: |
| persist-credentials: false |
| |
| - name: Setup Ruby and install dependencies |
| uses: ruby/setup-ruby@v1 |
| with: |
| bundler-cache: true |
| working-directory: bindings/ruby |
| |
| - name: Download gem artifacts |
| uses: actions/download-artifact@v5 |
| with: |
| pattern: opendal-ruby-gem-* |
| path: bindings/ruby/pkg/ |
| merge-multiple: true |
| |
| - name: List downloaded artifacts |
| run: | |
| echo "Downloaded gems:" |
| ls -lh pkg/*.gem |
| |
| # Adapted from rubygems/release-gem@v1. Changed: |
| # 1. publishing git tag |
| # 2. support custom working directory |
| # |
| # TODO: we can consider using rubygems/release-gem when the gem resolves: |
| # https://github.com/rubygems/release-gem/pull/12 |
| - name: Attribute commits to last committer |
| run: | |
| git config --global user.email "$(git log -1 --pretty=format:'%ae')" |
| git config --global user.name "$(git log -1 --pretty=format:'%an')" |
| |
| - name: Configure Git using cached credentials |
| run: | |
| git credential-cache --timeout=300 store <<EOF |
| protocol=https |
| host=github.com |
| username=x-access-token |
| password=${{ github.token }} |
| |
| EOF |
| git config --local credential.helper 'cache --timeout=300' |
| |
| # Patch file copied from |
| # https://github.com/rubygems/release-gem/blob/a25424ba2ba8b387abc8ef40807c2c85b96cbe32/rubygems-attestation-patch.rb |
| - name: Amend patch file |
| run: | |
| cat <<EOF >> rubygems-attestation-patch.rb |
| # frozen_string_literal: true |
| |
| return if RUBY_ENGINE == "jruby" |
| return unless defined?(Gem) |
| |
| require "rubygems/commands/push_command" |
| |
| Gem::Commands::PushCommand.prepend(Module.new do |
| def send_push_request(name, args) |
| return super if options[:attestations]&.any? || @host != "https://rubygems.org" |
| |
| begin |
| send_push_request_with_attestation(name, args) |
| rescue StandardError => e |
| alert_warning "Failed to push with attestation, retrying without attestation.\n#{e.full_message}" |
| super |
| end |
| end |
| |
| def send_push_request_with_attestation(name, args) |
| attestation = attest!(name) |
| if options[:attestations] |
| options[:attestations] << attestation |
| send_push_request(name, args) |
| else |
| rubygems_api_request(*args, scope: get_push_scope) do |request| |
| request.set_form([ |
| ["gem", Gem.read_binary(name), { filename: name, content_type: "application/octet-stream" }], |
| ["attestations", "[#{Gem.read_binary(attestation)}]", { content_type: "application/json" }] |
| ], "multipart/form-data") |
| request.add_field "Authorization", api_key |
| end |
| end |
| end |
| |
| def attest!(name) |
| require "open3" |
| bundle = "#{name}.sigstore.json" |
| env = defined?(Bundler.unbundled_env) ? Bundler.unbundled_env : ENV.to_h |
| out, st = Open3.capture2e( |
| env, |
| Gem.ruby, "-S", "gem", "exec", |
| "sigstore-cli:0.2.1", "sign", name, "--bundle", bundle, |
| unsetenv_others: true |
| ) |
| raise Gem::Exception, "Failed to sign gem:\n\n#{out}" unless st.success? |
| |
| bundle |
| end |
| end) |
| EOF |
| |
| - name: Configure trusted publishing credentials |
| uses: rubygems/configure-rubygems-credentials@v1.0.0 |
| |
| - name: Release gem |
| run: bundle exec rake release |
| env: |
| RUBYOPT: "${{ format('-r{0}/bindings/ruby/rubygems-attestation-patch.rb {1}', github.workspace, env.RUBYOPT) || env.RUBYOPT }}" |
| |
| - name: Wait for release to propagate |
| run: gem exec rubygems-await pkg/*.gem |
| |
| - name: Log Release |
| run: | |
| echo "## Ruby binding released! 🚀" >> "$GITHUB_STEP_SUMMARY" |
| echo "" >> "$GITHUB_STEP_SUMMARY" |
| echo "**Version:** $(bundle exec rake version)" >> "$GITHUB_STEP_SUMMARY" |
| echo "" >> "$GITHUB_STEP_SUMMARY" |
| echo "Check out the [RubyGems page](https://rubygems.org/gems/opendal) for more details." >> "$GITHUB_STEP_SUMMARY" |
| |
| - name: Clean up credentials |
| if: always() |
| run: git credential-cache exit || true |