Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 13 additions & 128 deletions .github/workflows/release_ruby.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# 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
Expand Down Expand Up @@ -92,14 +92,17 @@
fail-fast: false
matrix:
include:
- os: ubuntu-latest
- os: ubuntu-24.04
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
- os: macos-15
platform: arm64-darwin24
rust_target: aarch64-apple-darwin
- os: macos-26
platform: arm64-darwin25
rust_target: aarch64-apple-darwin

runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -154,12 +157,10 @@
# - reattempt standard tag releases
# - pre-releases

# if: >-
# startsWith(github.ref, 'refs/tags/v') ||
# (github.event_name == 'workflow_dispatch' && contains(needs.build.outputs.version, 'rc'))
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: ${{ vars.RUBY_RELEASE_ENABLED == 'true' }}
needs: [build, build-native]
runs-on: ubuntu-latest

Expand Down Expand Up @@ -187,122 +188,10 @@
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
shell: bash
run: |
oidc_token="$(curl -fsSL \
-H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
"${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=rubygems.org" \
| ruby -rjson -e 'puts JSON.parse(STDIN.read).fetch("value")')"
echo "::add-mask::${oidc_token}"

api_key="$(curl -fsSL \
-X POST https://rubygems.org/api/v1/oidc/trusted_publisher/exchange_token \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "User-Agent: apache-opendal-release" \
--data "{\"jwt\":\"${oidc_token}\"}" \
| ruby -rjson -e 'puts JSON.parse(STDIN.read).fetch("rubygems_api_key")')"
echo "::add-mask::${api_key}"

mkdir -p "${HOME}/.gem"
{
echo "---"
echo ":rubygems_api_key: ${api_key}"
} > "${HOME}/.gem/credentials"
chmod 0600 "${HOME}/.gem/credentials"
{
echo "RUBYGEMS_API_KEY=${api_key}"
echo "BUNDLE_GEM__PUSH_KEY=${api_key}"
echo "GEM_HOST_API_KEY=${api_key}"
} >> "${GITHUB_ENV}"

- 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: Release opendal gem
uses: rubygems/release-gem@f0d7faff26625599a847d40d9fa28ace24c2aacc # v1.2.0
with:
working-directory: bindings/ruby

- name: Log Release
run: |
Expand All @@ -311,7 +200,3 @@
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
Loading