From 5163cb85183f571b1771c5ee530cf5d590f28e50 Mon Sep 17 00:00:00 2001 From: doris-xiao-bybit Date: Wed, 22 Jul 2026 19:12:37 +0800 Subject: [PATCH 1/2] fix(rakefile): skip release:source_control_push on GitHub Actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `rubygems/release-gem@v1` hardcodes `bundle exec rake release`, and bundler/gem_tasks' `release:source_control_push` sub-task runs: git push origin refs/heads/ git push origin refs/tags/v Both fail on tag-triggered CI: 1. HEAD is detached (checked out at the tag SHA, not a branch), so `refs/heads/HEAD does not match any` — the push aborts before ever reaching `release:rubygem_push` (the OIDC gem-push step). 2. The tag was already pushed by the developer before the workflow ran (that push IS the trigger). Re-pushing is redundant. The workflow log confirms the sequence: bybit-connector-ruby 0.1.1 built to pkg/bybit-connector-ruby-0.1.1.gem Tagged v0.1.1. Untagging v0.1.1 due to error. rake aborted! Running `git push origin refs/heads/HEAD` failed Neutralize the sub-task on GitHub Actions only (guarded by $GITHUB_ACTIONS) so rake release proceeds straight to rubygem_push, which is the step that actually publishes via OIDC. Local `bundle exec rake release` behavior is unchanged for developers. With this fix the full release chain on CI is: release:guard_clean → verify clean tree (CI is always clean) release:source_control_push → NO-OP on GH Actions (this PR) release:rubygem_push → gem push, using GEM_HOST_API_KEY set by rubygems/release-gem's OIDC exchange Co-Authored-By: Claude Opus 4.7 (1M context) --- Rakefile | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Rakefile b/Rakefile index 9166c5e..10c19a1 100644 --- a/Rakefile +++ b/Rakefile @@ -8,3 +8,31 @@ RSpec::Core::RakeTask.new(:spec) RuboCop::RakeTask.new task default: %i[rubocop spec] + +# ── CI release fix ──────────────────────────────────────────────────────────── +# `bundle exec rake release` (invoked by rubygems/release-gem@v1) runs +# `release:source_control_push` which does: +# git push origin refs/heads/ +# git push origin refs/tags/v +# On tag-triggered CI: +# 1. HEAD is detached (checked out at the tag SHA, not a branch), so +# `refs/heads/HEAD` doesn't exist → `error: src refspec refs/heads/HEAD +# does not match any` and rake aborts. +# 2. The tag was already pushed by the developer — that's what triggered +# the workflow. Re-pushing it is redundant. +# +# Neutralize the sub-task on GitHub Actions so rake release proceeds to +# `release:rubygem_push`, which is the step that actually publishes to +# rubygems.org via OIDC. Local `bundle exec rake release` behavior is +# unchanged. +if ENV['GITHUB_ACTIONS'] == 'true' + if Rake::Task.task_defined?('release:source_control_push') + Rake::Task['release:source_control_push'].clear + end + namespace :release do + task :source_control_push do + puts '[release:source_control_push] SKIP on GitHub Actions ' \ + '(HEAD detached at tag; tag already pushed by developer).' + end + end +end From cbd2c502d631f825121b21c6d1dc5306b0aaa855 Mon Sep 17 00:00:00 2001 From: doris-xiao-bybit Date: Wed, 22 Jul 2026 19:32:33 +0800 Subject: [PATCH 2/2] style(rakefile): use if-modifier for task_defined? guard (rubocop) --- Rakefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Rakefile b/Rakefile index 10c19a1..7a78c9c 100644 --- a/Rakefile +++ b/Rakefile @@ -26,9 +26,7 @@ task default: %i[rubocop spec] # rubygems.org via OIDC. Local `bundle exec rake release` behavior is # unchanged. if ENV['GITHUB_ACTIONS'] == 'true' - if Rake::Task.task_defined?('release:source_control_push') - Rake::Task['release:source_control_push'].clear - end + Rake::Task['release:source_control_push'].clear if Rake::Task.task_defined?('release:source_control_push') namespace :release do task :source_control_push do puts '[release:source_control_push] SKIP on GitHub Actions ' \