From 5d6ef9e790620cdfe67a2c4d47ade1abbf1948e4 Mon Sep 17 00:00:00 2001 From: Eddie Li Date: Thu, 24 Sep 2026 12:46:05 +0800 Subject: [PATCH 1/3] =?UTF-8?q?Support=20Rails=208=20/=20Ruby=203.3?= =?UTF-8?q?=E2=80=933.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add required_ruby_version >= 2.7; loosen bundler/rake pins - Explicit ActiveSupport requires for delegate/blank (AS 8) - Add gemfiles for AS 7.2 and 8.0.5.1 plus GHA matrix - Fix Rakefile default task to :t --- .github/workflows/test.yml | 33 +++++++++++++++++++ Rakefile | 2 +- gemfiles/rails_7.2.gemfile | 12 +++++++ gemfiles/rails_7.2.gemfile.lock | 55 +++++++++++++++++++++++++++++++ gemfiles/rails_8.0.gemfile | 13 ++++++++ gemfiles/rails_8.0.gemfile.lock | 57 +++++++++++++++++++++++++++++++++ lib/warehouse.rb | 8 +++-- warehouse_items.gemspec | 6 ++-- 8 files changed, 180 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/test.yml create mode 100644 gemfiles/rails_7.2.gemfile create mode 100644 gemfiles/rails_7.2.gemfile.lock create mode 100644 gemfiles/rails_8.0.gemfile create mode 100644 gemfiles/rails_8.0.gemfile.lock diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..3d25a2a --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,33 @@ +name: Tests + +on: + push: + branches: [ master, main ] + pull_request: + branches: [ master, main ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - ruby: "3.3.12" + gemfile: gemfiles/rails_7.2.gemfile + - ruby: "3.3.12" + gemfile: gemfiles/rails_8.0.gemfile + - ruby: "3.4.11" + gemfile: gemfiles/rails_7.2.gemfile + - ruby: "3.4.11" + gemfile: gemfiles/rails_8.0.gemfile + env: + BUNDLE_GEMFILE: ${{ matrix.gemfile }} + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run tests + run: bundle exec rake t diff --git a/Rakefile b/Rakefile index ad85564..d19f038 100644 --- a/Rakefile +++ b/Rakefile @@ -7,4 +7,4 @@ Rake::TestTask.new(:t) do |t| t.test_files = FileList["test/**/*_test.rb"] end -task :default => :test +task :default => :t diff --git a/gemfiles/rails_7.2.gemfile b/gemfiles/rails_7.2.gemfile new file mode 100644 index 0000000..60768e3 --- /dev/null +++ b/gemfiles/rails_7.2.gemfile @@ -0,0 +1,12 @@ +# frozen_string_literal: true +source "https://rubygems.org" + +gemspec path: ".." + +gem "activesupport", "~> 7.2.0" +gem "rake", ">= 13" +gem "minitest", "~> 5.0" +gem "shoulda-context" +gem "logger" +gem "mutex_m" +gem "bigdecimal" diff --git a/gemfiles/rails_7.2.gemfile.lock b/gemfiles/rails_7.2.gemfile.lock new file mode 100644 index 0000000..6f4cb76 --- /dev/null +++ b/gemfiles/rails_7.2.gemfile.lock @@ -0,0 +1,55 @@ +PATH + remote: .. + specs: + warehouse_items (1.0.0) + activesupport + +GEM + remote: https://rubygems.org/ + specs: + activesupport (7.2.3.2) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1, < 6) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + base64 (0.3.0) + benchmark (0.5.0) + bigdecimal (4.1.3) + concurrent-ruby (1.3.8) + connection_pool (3.0.2) + drb (2.2.3) + i18n (1.15.2) + concurrent-ruby (~> 1.0) + logger (1.7.0) + minitest (5.27.0) + mutex_m (0.3.0) + rake (13.4.2) + securerandom (0.4.1) + shoulda-context (2.0.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + +PLATFORMS + ruby + x86_64-linux + +DEPENDENCIES + activesupport (~> 7.2.0) + bigdecimal + bundler (>= 1.16) + logger + minitest (~> 5.0) + mutex_m + rake (>= 13, >= 10.0) + shoulda-context + warehouse_items! + +BUNDLED WITH + 2.7.2 diff --git a/gemfiles/rails_8.0.gemfile b/gemfiles/rails_8.0.gemfile new file mode 100644 index 0000000..e23e00e --- /dev/null +++ b/gemfiles/rails_8.0.gemfile @@ -0,0 +1,13 @@ +# frozen_string_literal: true +source "https://rubygems.org" + +gemspec path: ".." + +# Target Rails 8.0.5.1 ActiveSupport (8.1.3.1 also exists on RubyGems) +gem "activesupport", "8.0.5.1" +gem "rake", ">= 13" +gem "minitest", "~> 5.0" +gem "shoulda-context" +gem "logger" +gem "mutex_m" +gem "bigdecimal" diff --git a/gemfiles/rails_8.0.gemfile.lock b/gemfiles/rails_8.0.gemfile.lock new file mode 100644 index 0000000..8dc382e --- /dev/null +++ b/gemfiles/rails_8.0.gemfile.lock @@ -0,0 +1,57 @@ +PATH + remote: .. + specs: + warehouse_items (1.0.0) + activesupport + +GEM + remote: https://rubygems.org/ + specs: + activesupport (8.0.5.1) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + base64 (0.3.0) + benchmark (0.5.0) + bigdecimal (4.1.3) + concurrent-ruby (1.3.8) + connection_pool (3.0.2) + drb (2.2.3) + i18n (1.15.2) + concurrent-ruby (~> 1.0) + logger (1.7.0) + minitest (5.27.0) + mutex_m (0.3.0) + rake (13.4.2) + securerandom (0.4.1) + shoulda-context (2.0.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uri (1.1.1) + +PLATFORMS + ruby + x86_64-linux + +DEPENDENCIES + activesupport (= 8.0.5.1) + bigdecimal + bundler (>= 1.16) + logger + minitest (~> 5.0) + mutex_m + rake (>= 13, >= 10.0) + shoulda-context + warehouse_items! + +BUNDLED WITH + 2.7.2 diff --git a/lib/warehouse.rb b/lib/warehouse.rb index e179bee..bdeb462 100644 --- a/lib/warehouse.rb +++ b/lib/warehouse.rb @@ -1,7 +1,9 @@ require "warehouse/version" -require 'active_support/core_ext/object' -require 'active_support/core_ext/class' -require 'active_support' +require "active_support" +require "active_support/core_ext/object" +require "active_support/core_ext/object/blank" +require "active_support/core_ext/module/delegation" +require "active_support/core_ext/class" require "warehouse/item/code" require "warehouse/item/barcode" require "warehouse/item/random" diff --git a/warehouse_items.gemspec b/warehouse_items.gemspec index 5a410d5..f756c15 100644 --- a/warehouse_items.gemspec +++ b/warehouse_items.gemspec @@ -14,6 +14,8 @@ Gem::Specification.new do |spec| spec.homepage = "https://github.com/superlanding/warehouse_items" spec.license = "MIT" + spec.required_ruby_version = ">= 2.7" + # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do @@ -23,8 +25,8 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_development_dependency "bundler", "~> 1.16" - spec.add_development_dependency "rake", "~> 10.0" + spec.add_development_dependency "bundler", ">= 1.16" + spec.add_development_dependency "rake", ">= 10.0" spec.add_development_dependency "minitest", "~> 5.0" spec.add_development_dependency "shoulda-context" From 235ce1896e3ccf33908ba4d5d8d7b1648e520284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=99=E6=B0=B4=E5=BF=8D?= <335298362+sensui624@users.noreply.github.com> Date: Fri, 23 Oct 2026 15:28:40 +0800 Subject: [PATCH 2/3] ci: add RubyGems trusted publishing workflow --- .github/workflows/publish.yml | 121 ++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..10b6f7d --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,121 @@ +name: Publish gem + +# master 上 gemspec 版本號尚未發佈到 rubygems.org 時,自動以 Trusted Publishing (OIDC) 發佈。 +# 版本已存在則跳過;不使用任何儲存的 RubyGems API key。 +on: + push: + branches: + - master + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: publish-gem-${{ github.repository }} + cancel-in-progress: false + +env: + # 與 test.yml 矩陣中最新的 Ruby 3.4.11 / Rails 8.0 組合一致 + RUBY_VERSION: '3.4.11' + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_8.0.gemfile + GEM_NAME: warehouse_items + GEMSPEC: warehouse_items.gemspec + +jobs: + check: + name: Check version on rubygems.org + runs-on: ubuntu-latest + outputs: + should_publish: ${{ steps.check.outputs.should_publish }} + gem_name: ${{ steps.spec.outputs.name }} + gem_version: ${{ steps.spec.outputs.version }} + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - uses: ruby/setup-ruby@b1da4809b005e0178fe08a1d57317bffc00b7b4c # v1.332.0 + with: + ruby-version: ${{ env.RUBY_VERSION }} + + - name: Read gem name and version from gemspec + id: spec + run: | + ruby -e 'spec = Gem::Specification.load(ENV.fetch("GEMSPEC")) or abort("cannot load #{ENV["GEMSPEC"]}"); abort("gemspec name #{spec.name} != #{ENV["GEM_NAME"]}") unless spec.name == ENV["GEM_NAME"]; puts "name=#{spec.name}"; puts "version=#{spec.version}"' >> "$GITHUB_OUTPUT" + cat "$GITHUB_OUTPUT" + + - name: Check whether this version already exists on rubygems.org + id: check + env: + GEM_NAME: ${{ steps.spec.outputs.name }} + GEM_VERSION: ${{ steps.spec.outputs.version }} + run: | + set -euo pipefail + status=$(curl -sS -o versions.json -w '%{http_code}' "https://rubygems.org/api/v1/versions/${GEM_NAME}.json") + if [ "$status" = "404" ]; then + echo "Gem ${GEM_NAME} not found on rubygems.org; will publish." + echo "should_publish=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + if [ "$status" != "200" ]; then + echo "::error::rubygems.org API returned HTTP ${status}" + exit 1 + fi + if jq -e --arg v "$GEM_VERSION" 'any(.[]; .number == $v)' versions.json > /dev/null; then + echo "${GEM_NAME} ${GEM_VERSION} already on rubygems.org; skip publish." + echo "should_publish=false" >> "$GITHUB_OUTPUT" + else + echo "${GEM_NAME} ${GEM_VERSION} not on rubygems.org yet; will publish." + echo "should_publish=true" >> "$GITHUB_OUTPUT" + fi + + test: + name: Test (Ruby 3.4 / Rails 8.0) + needs: check + if: needs.check.outputs.should_publish == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - uses: ruby/setup-ruby@b1da4809b005e0178fe08a1d57317bffc00b7b4c # v1.332.0 + with: + ruby-version: ${{ env.RUBY_VERSION }} + bundler-cache: true + + - run: bundle exec rake t + + publish: + name: Publish ${{ needs.check.outputs.gem_name }} ${{ needs.check.outputs.gem_version }} + needs: [check, test] + if: needs.check.outputs.should_publish == 'true' && github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + environment: gem-publish + permissions: + id-token: write # Trusted Publishing (OIDC) + contents: write # rake release 推送 vX.Y.Z tag + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - uses: ruby/setup-ruby@b1da4809b005e0178fe08a1d57317bffc00b7b4c # v1.332.0 + with: + ruby-version: ${{ env.RUBY_VERSION }} + bundler-cache: true + + # setup-ruby 的 bundler-cache 會把 BUNDLE_PATH 等設定寫進 .bundle/config, + # 若該檔被 git 追蹤,rake release 的 guard_clean 會判定工作目錄不乾淨。 + # 目前此 repo 沒有追蹤任何 .bundle/config;這一步對「有追蹤才標記」做容錯處理, + # 日後若加入 gemfiles/.bundle/config 或 .bundle/config 也不會讓發佈失敗。 + - name: Ignore CI-only bundler config change + run: | + git status --porcelain + git ls-files -z '*.bundle/config' | xargs -0 -r git update-index --assume-unchanged + git status --porcelain + + # 透過 rubygems/configure-rubygems-credentials 取得短效 OIDC token, + # 再執行 bundle exec rake release(build、建立並推送 vX.Y.Z tag、push gem) + - uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1 From 466cd768347ab88f3755794f33e0aadc9dd6635f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=99=E6=B0=B4=E5=BF=8D?= <335298362+sensui624@users.noreply.github.com> Date: Tue, 27 Oct 2026 10:25:20 +0800 Subject: [PATCH 3/3] docs: add CLAUDE.md version bump rule --- CLAUDE.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..13afd4b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,9 @@ +# CLAUDE.md + +## 發版規則(Ruby gem) + +- 這個 gem(`warehouse_items`,gemspec:`warehouse_items.gemspec`)在 master 收到「新版本號」時,由 GitHub Actions(`.github/workflows/publish.yml`)自動發佈到 rubygems.org(Trusted Publishing,不使用 API key)。 +- **每一個 PR 都必須跳版號**(改 `lib/warehouse/version.rb`),除非這個 PR 只改文件、CI 或 CLAUDE.md 且明確不需要發版。沒跳版號的 PR 合進 master 後不會發佈。 +- 跳版規則(Semantic Versioning):修 bug 跳 patch(x.y.Z);新增相容功能跳 minor(x.Y.0);不相容變更跳 major(X.0.0)。 +- 版號只改在 PR 裡。AI 帳號只能開 branch 與 PR,不得合併到 master;只有真人帳號可以合併。合併就等於批准發佈。 +- 不得為了讓測試通過而改變程式原本的行為。