From daaf9edfaff4ec7c896198abe579ac125d2656ef Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 10:16:11 +0800 Subject: [PATCH 01/12] Fix remaining compatibility issues (#9, #10, #14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #9: Remove Bankai::RUBY_VERSION constant that shadowed Ruby built-in, templates now correctly use the actual Ruby version - #10: Modernize GitLab CI template — remove Node.js/Yarn setup, remove yarn-audit job, update Postgres to 16, MySQL to 8.0, remove hardcoded BUNDLER_VERSION, use bundled brakeman/bundler-audit - #14: Detect trilogy adapter in mysql? helper Closes #9 #10 #14 Co-Authored-By: Claude Opus 4.6 --- lib/bankai/helper.rb | 2 +- lib/bankai/version.rb | 1 - templates/gitlab-ci.yml.erb | 53 +++++-------------------------------- 3 files changed, 7 insertions(+), 49 deletions(-) diff --git a/lib/bankai/helper.rb b/lib/bankai/helper.rb index b372ec6..82f816e 100644 --- a/lib/bankai/helper.rb +++ b/lib/bankai/helper.rb @@ -10,7 +10,7 @@ def pg? end def mysql? - gemfile.match?(/gem .mysql2./) + gemfile.match?(/gem .(mysql2|trilogy)./) end def capistrano? diff --git a/lib/bankai/version.rb b/lib/bankai/version.rb index 27a00be..6c8fe07 100644 --- a/lib/bankai/version.rb +++ b/lib/bankai/version.rb @@ -2,7 +2,6 @@ module Bankai VERSION = '0.13.4' - RUBY_VERSION = '2.6.7' RAILS_VERSION = '7.0.0' RUBOCOP_VERSION = '1.24.1' CAPISTRANO_VERSION = '3.16.0' diff --git a/templates/gitlab-ci.yml.erb b/templates/gitlab-ci.yml.erb index fb96503..ba278fb 100644 --- a/templates/gitlab-ci.yml.erb +++ b/templates/gitlab-ci.yml.erb @@ -8,10 +8,6 @@ stages: variables: RAILS_ENV: test -<%- unless options.api? -%> - NODE_VERSION: 12.13.1 -<%- end -%> - BUNDLER_VERSION: 2.2.26 <%- if pg? -%> POSTGRES_DB: <%= app_name %> POSTGRES_PASSWORD: postgres @@ -26,14 +22,7 @@ variables: <%- end -%> .install_ruby_gems: &install_ruby_gems - - gem install bundler -v ${BUNDLER_VERSION} - bundle install --path vendor -<% unless options.api? %> -.install_nodejs: &install_nodejs - - curl -SLO https://nodejs.org/dist/v$NODE_VERSION/node-v${NODE_VERSION}-linux-x64.tar.xz && tar -xJf node-v${NODE_VERSION}-linux-x64.tar.xz -C /usr/local --strip-components=1; - - curl -o- -L https://yarnpkg.com/install.sh | bash - - export PATH=$HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$PATH -<% end -%> .common: before_script: @@ -44,14 +33,8 @@ variables: key: files: - Gemfile.lock -<%- unless options.api? -%> - - yarn.lock -<%- end -%> paths: - vendor/ruby -<% unless options.api? %> - - node_modules -<% end -%> rubocop: extends: .common @@ -62,14 +45,11 @@ rubocop: - if: $CI_MERGE_REQUEST_ID brakeman: - image: registry.gitlab.com/gitlab-org/security-products/analyzers/brakeman:2 + extends: .common stage: lint allow_failure: true script: - - /analyzer run - artifacts: - reports: - sast: gl-sast-report.json + - bundle exec brakeman -q --no-pager rules: - if: $CI_MERGE_REQUEST_ID @@ -77,9 +57,7 @@ bundler-audit: extends: .common stage: lint script: - - gem install bundler-audit - - bundle audit --update - - bundle audit + - bundle exec bundler-audit --update rules: - if: $CI_MERGE_REQUEST_ID - if: $CI_PIPELINE_SOURCE == 'schedule' @@ -95,36 +73,17 @@ bundler-leak: rules: - if: $CI_MERGE_REQUEST_ID - if: $CI_PIPELINE_SOURCE == 'schedule' -<% unless options.api? %> -yarn-audit: - extends: .common - stage: lint - before_script: - - *install_nodejs - script: - - yarn audit - rules: - - if: $CI_MERGE_REQUEST_ID - - if: $CI_PIPELINE_SOURCE == 'schedule' - allow_failure: true -<% end -%> rspec: extends: .common stage: test - before_script: - - *install_ruby_gems -<%- unless options.api? -%> - - *install_nodejs - - yarn install -<%- end -%> services: <%- if pg? -%> - - postgres:12-alpine + - postgres:16-alpine <%- end -%> <%- if mysql? -%> - - name: mysql:5.7 - command: ['mysqld', '--character-set-server=utf8', '--collation-server=utf8_unicode_ci'] + - name: mysql:8.0 + command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci'] <%- end -%> script: - bundle exec rake db:migrate From cc696535f691a978711385a82f831db8b8d5a710 Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 10:28:21 +0800 Subject: [PATCH 02/12] Add unit tests for Helper/Version and GitHub Actions CI - Move version test from spec/bankai_spec.rb to spec/bankai/version_spec.rb - Add helper_spec.rb testing pg?, mysql?, capistrano? methods - Add CI workflow running RSpec across Ruby 3.2/3.3/3.4/4.0 Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 30 +++++++++++++++++++ spec/bankai/helper_spec.rb | 59 +++++++++++++++++++++++++++++++++++++ spec/bankai/version_spec.rb | 43 +++++++++++++++++++++++++++ spec/bankai_spec.rb | 7 ----- 4 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 spec/bankai/helper_spec.rb create mode 100644 spec/bankai/version_spec.rb delete mode 100644 spec/bankai_spec.rb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..dd75af9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + ruby-version: ['3.2', '3.3', '3.4', '4.0'] + + name: Ruby ${{ matrix.ruby-version }} + + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby ${{ matrix.ruby-version }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true + + - name: Run tests + run: bundle exec rspec diff --git a/spec/bankai/helper_spec.rb b/spec/bankai/helper_spec.rb new file mode 100644 index 0000000..2f49f4f --- /dev/null +++ b/spec/bankai/helper_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +RSpec.describe Bankai::Helper do + let(:test_instance) do + klass = Class.new do + include Bankai::Helper + + attr_accessor :destination_root + + public :pg?, :mysql?, :capistrano? + end + klass.new + end + + before do + test_instance.destination_root = '/tmp/fake_app' + end + + describe '#pg?' do + it 'returns true when Gemfile contains pg' do + allow(File).to receive(:read).with('/tmp/fake_app/Gemfile').and_return("gem 'pg'") + expect(test_instance.pg?).to be true + end + + it 'returns false when Gemfile contains mysql2' do + allow(File).to receive(:read).with('/tmp/fake_app/Gemfile').and_return("gem 'mysql2'") + expect(test_instance.pg?).to be false + end + end + + describe '#mysql?' do + it 'returns true when Gemfile contains mysql2' do + allow(File).to receive(:read).with('/tmp/fake_app/Gemfile').and_return("gem 'mysql2'") + expect(test_instance.mysql?).to be true + end + + it 'returns true when Gemfile contains trilogy' do + allow(File).to receive(:read).with('/tmp/fake_app/Gemfile').and_return("gem 'trilogy'") + expect(test_instance.mysql?).to be true + end + + it 'returns false when Gemfile contains pg' do + allow(File).to receive(:read).with('/tmp/fake_app/Gemfile').and_return("gem 'pg'") + expect(test_instance.mysql?).to be false + end + end + + describe '#capistrano?' do + it 'returns true when Gemfile contains capistrano' do + allow(File).to receive(:read).with('/tmp/fake_app/Gemfile').and_return("gem 'capistrano'") + expect(test_instance.capistrano?).to be true + end + + it 'returns false when Gemfile does not contain capistrano' do + allow(File).to receive(:read).with('/tmp/fake_app/Gemfile').and_return("gem 'pg'") + expect(test_instance.capistrano?).to be false + end + end +end diff --git a/spec/bankai/version_spec.rb b/spec/bankai/version_spec.rb new file mode 100644 index 0000000..379503b --- /dev/null +++ b/spec/bankai/version_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +RSpec.describe Bankai do + describe 'VERSION' do + it 'is defined' do + expect(Bankai::VERSION).not_to be_nil + end + + it 'follows semver format' do + expect(Bankai::VERSION).to match(/\A\d+\.\d+\.\d+\z/) + end + end + + describe 'RAILS_VERSION' do + it 'is defined' do + expect(Bankai::RAILS_VERSION).not_to be_nil + end + + it 'follows semver format' do + expect(Bankai::RAILS_VERSION).to match(/\A\d+\.\d+\.\d+\z/) + end + end + + describe 'RUBOCOP_VERSION' do + it 'is defined' do + expect(Bankai::RUBOCOP_VERSION).not_to be_nil + end + + it 'follows semver format' do + expect(Bankai::RUBOCOP_VERSION).to match(/\A\d+\.\d+\.\d+\z/) + end + end + + describe 'CAPISTRANO_VERSION' do + it 'is defined' do + expect(Bankai::CAPISTRANO_VERSION).not_to be_nil + end + + it 'follows semver format' do + expect(Bankai::CAPISTRANO_VERSION).to match(/\A\d+\.\d+\.\d+\z/) + end + end +end diff --git a/spec/bankai_spec.rb b/spec/bankai_spec.rb deleted file mode 100644 index b9126fe..0000000 --- a/spec/bankai_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Bankai do - it 'has a version number' do - expect(Bankai::VERSION).not_to be nil - end -end From c2e1a0ed2e1e1a8f7640669c39e21509fd8bd513 Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 10:42:40 +0800 Subject: [PATCH 03/12] Trigger CI on fix/** and feature/** branch pushes Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd75af9..09b775a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [master] + branches: [master, 'fix/**', 'feature/**'] pull_request: branches: [master] From 4380654a8953943e4c8f339c9de1618193c349ad Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 10:52:57 +0800 Subject: [PATCH 04/12] Add integration test for generator end-to-end flow Runs exe/bankai in a subprocess to generate a full Rails project, verifying Gemfile contents, static files, config injection, and directory structure. Tagged :slow for easy filtering. Co-Authored-By: Claude Opus 4.6 --- spec/bankai/generator_spec.rb | 131 ++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 spec/bankai/generator_spec.rb diff --git a/spec/bankai/generator_spec.rb b/spec/bankai/generator_spec.rb new file mode 100644 index 0000000..501c489 --- /dev/null +++ b/spec/bankai/generator_spec.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +require 'tmpdir' +require 'fileutils' + +RSpec.describe Bankai::Generator, :slow do + before(:all) do + @tmpdir = Dir.mktmpdir('bankai_test_') + @project_path = File.join(@tmpdir, 'testapp') + + gem_root = File.expand_path('../..', __dir__) + bankai_bin = File.join(gem_root, 'exe', 'bankai') + + Bundler.with_unbundled_env do + success = system( + 'ruby', bankai_bin, 'testapp', + '--database=sqlite3', + '--skip-rspec', + "--path=#{gem_root}", + chdir: @tmpdir + ) + raise "Generator failed (exit #{$?.exitstatus})" unless success + end + end + + after(:all) do + FileUtils.remove_entry(@tmpdir) if @tmpdir + end + + def project_file(*path) + File.join(@project_path, *path) + end + + def read_project_file(*path) + File.read(project_file(*path)) + end + + describe 'Gemfile' do + subject(:gemfile) { read_project_file('Gemfile') } + + it 'includes rails' do + expect(gemfile).to match(/gem ['"]rails['"]/) + end + + it 'includes database adapter' do + expect(gemfile).to match(/gem ['"]sqlite3['"]/) + end + + it 'includes bankai' do + expect(gemfile).to match(/gem ['"]bankai['"]/) + end + end + + describe 'static files' do + it 'generates README.md' do + expect(File).to exist(project_file('README.md')) + end + + it 'generates .gitignore' do + expect(File).to exist(project_file('.gitignore')) + end + + it 'generates .env.example' do + expect(File).to exist(project_file('.env.example')) + end + + it 'generates .ctags' do + expect(File).to exist(project_file('.ctags')) + end + + it 'generates .gitlab-ci.yml' do + expect(File).to exist(project_file('.gitlab-ci.yml')) + end + + it 'generates .overcommit.yml' do + expect(File).to exist(project_file('.overcommit.yml')) + end + + it 'generates rack_mini_profiler initializer' do + expect(File).to exist(project_file('config', 'initializers', 'rack_mini_profiler.rb')) + end + + it 'generates oj initializer' do + expect(File).to exist(project_file('config', 'initializers', 'oj.rb')) + end + end + + describe 'configuration injection' do + it 'configures generators with rspec in application.rb' do + content = read_project_file('config', 'application.rb') + expect(content).to include('test_framework :rspec') + end + + it 'configures quiet assets in application.rb' do + content = read_project_file('config', 'application.rb') + expect(content).to include('config.assets.quiet = true') + end + + it 'configures puma-dev host in development.rb' do + content = read_project_file('config', 'environments', 'development.rb') + expect(content).to include('.test') + end + + it 'configures Bullet in development.rb' do + content = read_project_file('config', 'environments', 'development.rb') + expect(content).to include('Bullet.enable') + end + + it 'configures letter_opener in development.rb' do + content = read_project_file('config', 'environments', 'development.rb') + expect(content).to include('letter_opener') + end + + it 'clears db/seeds.rb' do + expect(read_project_file('db', 'seeds.rb')).to be_empty + end + end + + describe 'directory structure' do + %w[ + spec/lib/.keep + spec/controllers/.keep + spec/helpers/.keep + spec/support/matchers/.keep + ].each do |path| + it "creates #{path}" do + expect(File).to exist(project_file(path)) + end + end + end +end From 551eca97e9689535053f57e6535fa0d92a2f9f78 Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 10:58:05 +0800 Subject: [PATCH 05/12] Fix CI: remove Bundler.with_unbundled_env from integration test On CI with bundler-cache, gems live in vendor/bundle. Clearing the bundler env made rails unloadable in the subprocess. Let the subprocess inherit the bundle exec context instead; the generator's internal Bundler.with_original_env handles isolation for bundle install. Also capture subprocess output for better error diagnostics. Co-Authored-By: Claude Opus 4.6 --- spec/bankai/generator_spec.rb | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/spec/bankai/generator_spec.rb b/spec/bankai/generator_spec.rb index 501c489..d2f869c 100644 --- a/spec/bankai/generator_spec.rb +++ b/spec/bankai/generator_spec.rb @@ -2,6 +2,7 @@ require 'tmpdir' require 'fileutils' +require 'open3' RSpec.describe Bankai::Generator, :slow do before(:all) do @@ -11,16 +12,14 @@ gem_root = File.expand_path('../..', __dir__) bankai_bin = File.join(gem_root, 'exe', 'bankai') - Bundler.with_unbundled_env do - success = system( - 'ruby', bankai_bin, 'testapp', - '--database=sqlite3', - '--skip-rspec', - "--path=#{gem_root}", - chdir: @tmpdir - ) - raise "Generator failed (exit #{$?.exitstatus})" unless success - end + output, status = Open3.capture2e( + 'ruby', bankai_bin, 'testapp', + '--database=sqlite3', + '--skip-rspec', + "--path=#{gem_root}", + chdir: @tmpdir + ) + raise "Generator failed (exit #{status.exitstatus}):\n#{output.lines.last(30).join}" unless status.success? end after(:all) do From f8456aeceb6a8641ce8605c1b3f4e9e280564cc1 Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 11:04:21 +0800 Subject: [PATCH 06/12] Fix Bundler 4.0 compat: use with_original_env instead of with_unbundled_env Bundler.with_unbundled_env clears GEM_HOME/GEM_PATH, which on Bundler 4.0 (Ruby 4.0) makes gems unfindable when sub-generators call bin/rails. Rails itself uses Bundler.with_original_env in bundle_command (see railties bundle_helper.rb), so we follow the same pattern for generate_default and rails_command. Co-Authored-By: Claude Opus 4.6 --- lib/bankai/generator.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bankai/generator.rb b/lib/bankai/generator.rb index 335c410..49018da 100644 --- a/lib/bankai/generator.rb +++ b/lib/bankai/generator.rb @@ -82,7 +82,7 @@ def setup_dotfiles def generate_default run('bundle binstubs bundler') - Bundler.with_unbundled_env do + Bundler.with_original_env do generate('bankai:testing') unless options[:skip_rspec] generate('bankai:ci', options.api? ? '--api' : '') generate('bankai:json') @@ -109,7 +109,7 @@ def self.banner protected def rails_command(command, command_options = {}) - Bundler.with_unbundled_env { super } + Bundler.with_original_env { super } end # rubocop:disable Naming/AccessorMethodName From 3e2e1bd5708404c8bb2b4f41ef06fdcaaf38fa5c Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 11:35:43 +0800 Subject: [PATCH 07/12] Add diagnostic output for Ruby 4.0 CI bundler debugging Show full generator output on failure and bundler env info to diagnose why sub-generators can't find gems on CI. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 18 ++++++++++++++++++ spec/bankai/generator_spec.rb | 10 +++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09b775a..217f1a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,5 +26,23 @@ jobs: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true + - name: Debug bundler env + run: | + echo "=== Ruby & Bundler ===" + ruby -v + bundle -v + echo "=== Key env vars ===" + echo "GEM_HOME=$GEM_HOME" + echo "GEM_PATH=$GEM_PATH" + echo "BUNDLE_PATH=$BUNDLE_PATH" + echo "BUNDLE_APP_CONFIG=$BUNDLE_APP_CONFIG" + echo "BUNDLE_GEMFILE=$BUNDLE_GEMFILE" + echo "=== Bundle config ===" + bundle config list + echo "=== Gem paths ===" + ruby -e 'puts "Gem.dir=#{Gem.dir}"; puts "Gem.default_dir=#{Gem.default_dir}"; puts "Gem.user_dir=#{Gem.user_dir}"; puts "Gem.path=#{Gem.path}"' + echo "=== Inside bundle exec ===" + bundle exec ruby -e 'require "open3"; out,_=Open3.capture2e("ruby","-e","require %q(bundler); Bundler.with_original_env { puts %Q(orig GEM_HOME=\#{ENV[%q(GEM_HOME)]}) }; Bundler.with_unbundled_env { puts %Q(unbundled GEM_HOME=\#{ENV[%q(GEM_HOME)]}) }; puts %Q(Gem.default_dir=\#{Gem.default_dir})"); puts out' + - name: Run tests run: bundle exec rspec diff --git a/spec/bankai/generator_spec.rb b/spec/bankai/generator_spec.rb index d2f869c..9f89bcd 100644 --- a/spec/bankai/generator_spec.rb +++ b/spec/bankai/generator_spec.rb @@ -19,7 +19,15 @@ "--path=#{gem_root}", chdir: @tmpdir ) - raise "Generator failed (exit #{status.exitstatus}):\n#{output.lines.last(30).join}" unless status.success? + unless status.success? + diag = "Ruby: #{RUBY_VERSION}, Bundler: #{Bundler::VERSION}\n" + diag += "GEM_HOME: #{ENV['GEM_HOME']}\n" + diag += "Gem.default_dir: #{Gem.default_dir}\n" + diag += "BUNDLE_GEMFILE: #{ENV['BUNDLE_GEMFILE']}\n" + diag += "Gemfile.lock exists: #{File.exist?(File.join(@project_path, 'Gemfile.lock'))}\n" + diag += ".bundle/config exists: #{File.exist?(File.join(@project_path, '.bundle', 'config'))}\n" + raise "Generator failed (exit #{status.exitstatus}):\n\n--- Diagnostics ---\n#{diag}\n--- Full output ---\n#{output}" + end end after(:all) do From 44649a4e62827ce365515dd1efda8b0064d94fb7 Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 11:36:25 +0800 Subject: [PATCH 08/12] Revert CI branch trigger to master-only Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 217f1a3..b6a29c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [master, 'fix/**', 'feature/**'] + branches: [master] pull_request: branches: [master] From 9d50c996f77ab1c800056da5aebd447bd03f274e Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 11:46:01 +0800 Subject: [PATCH 09/12] Fix CI: set sticky bit on gem dir for Bundler 4.0 security check Bundler 4.0's `strict_rm_rf` refuses to reinstall default gems (like erb-6.0.1) when the parent directory is world-writable without the sticky bit. GitHub Actions runners may have permissive permissions on the Ruby gem directory, causing `bundle install` to fail with InsecureInstallPathError during project generation. Fix by setting the sticky bit on the default gems directory in CI. Also keep diagnostic output in test error messages for easier debugging. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 25 +++++++++---------------- spec/bankai/generator_spec.rb | 2 +- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6a29c5..f5f0212 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,23 +26,16 @@ jobs: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true - - name: Debug bundler env + - name: Fix default gem directory permissions run: | - echo "=== Ruby & Bundler ===" - ruby -v - bundle -v - echo "=== Key env vars ===" - echo "GEM_HOME=$GEM_HOME" - echo "GEM_PATH=$GEM_PATH" - echo "BUNDLE_PATH=$BUNDLE_PATH" - echo "BUNDLE_APP_CONFIG=$BUNDLE_APP_CONFIG" - echo "BUNDLE_GEMFILE=$BUNDLE_GEMFILE" - echo "=== Bundle config ===" - bundle config list - echo "=== Gem paths ===" - ruby -e 'puts "Gem.dir=#{Gem.dir}"; puts "Gem.default_dir=#{Gem.default_dir}"; puts "Gem.user_dir=#{Gem.user_dir}"; puts "Gem.path=#{Gem.path}"' - echo "=== Inside bundle exec ===" - bundle exec ruby -e 'require "open3"; out,_=Open3.capture2e("ruby","-e","require %q(bundler); Bundler.with_original_env { puts %Q(orig GEM_HOME=\#{ENV[%q(GEM_HOME)]}) }; Bundler.with_unbundled_env { puts %Q(unbundled GEM_HOME=\#{ENV[%q(GEM_HOME)]}) }; puts %Q(Gem.default_dir=\#{Gem.default_dir})"); puts out' + # Bundler 4.0 refuses to reinstall default gems when the parent + # directory is world-writable without sticky bit (InsecureInstallPathError). + # GitHub Actions runners may have permissive permissions on the Ruby + # gem directory. Set the sticky bit to satisfy Bundler's security check. + gem_dir=$(ruby -e 'puts Gem.default_dir') + if [ -d "$gem_dir/gems" ]; then + chmod +t "$gem_dir/gems" 2>/dev/null || true + fi - name: Run tests run: bundle exec rspec diff --git a/spec/bankai/generator_spec.rb b/spec/bankai/generator_spec.rb index 9f89bcd..c915f29 100644 --- a/spec/bankai/generator_spec.rb +++ b/spec/bankai/generator_spec.rb @@ -26,7 +26,7 @@ diag += "BUNDLE_GEMFILE: #{ENV['BUNDLE_GEMFILE']}\n" diag += "Gemfile.lock exists: #{File.exist?(File.join(@project_path, 'Gemfile.lock'))}\n" diag += ".bundle/config exists: #{File.exist?(File.join(@project_path, '.bundle', 'config'))}\n" - raise "Generator failed (exit #{status.exitstatus}):\n\n--- Diagnostics ---\n#{diag}\n--- Full output ---\n#{output}" + raise "Generator failed (exit #{status.exitstatus}):\n\n--- Diagnostics ---\n#{diag}\n--- Output (last 80 lines) ---\n#{output.lines.last(80).join}" end end From fd36745b4ae3329e19439e8877cc29bd610c17bb Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 12:00:33 +0800 Subject: [PATCH 10/12] Add Rails version to CI test matrix (4x4: Ruby x Rails) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test Ruby (3.2, 3.3, 3.4, 4.0) × Rails (7.0, 7.1, 7.2, 8.1) = 16 jobs. RAILS_VERSION env var in Gemfile pins Rails via ~> constraint; unset keeps current behavior. Separate bundle caches per Rails version. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 11 ++++++----- Gemfile | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f5f0212..9d0b5be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,8 +14,12 @@ jobs: fail-fast: false matrix: ruby-version: ['3.2', '3.3', '3.4', '4.0'] + rails-version: ['7.0', '7.1', '7.2', '8.1'] - name: Ruby ${{ matrix.ruby-version }} + name: Ruby ${{ matrix.ruby-version }} / Rails ${{ matrix.rails-version }} + + env: + RAILS_VERSION: ${{ matrix.rails-version }} steps: - uses: actions/checkout@v4 @@ -25,13 +29,10 @@ jobs: with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true + cache-version: rails-${{ matrix.rails-version }} - name: Fix default gem directory permissions run: | - # Bundler 4.0 refuses to reinstall default gems when the parent - # directory is world-writable without sticky bit (InsecureInstallPathError). - # GitHub Actions runners may have permissive permissions on the Ruby - # gem directory. Set the sticky bit to satisfy Bundler's security check. gem_dir=$(ruby -e 'puts Gem.default_dir') if [ -d "$gem_dir/gems" ]; then chmod +t "$gem_dir/gems" 2>/dev/null || true diff --git a/Gemfile b/Gemfile index 013bdf1..edfad56 100644 --- a/Gemfile +++ b/Gemfile @@ -6,3 +6,7 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } # Specify your gem's dependencies in bankai.gemspec gemspec + +if ENV['RAILS_VERSION'] + gem 'rails', "~> #{ENV['RAILS_VERSION']}.0" +end From 293bcf64f3d16cc633e9d5da2fa7f9b46d4b3f18 Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 12:04:55 +0800 Subject: [PATCH 11/12] Add ignore files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5c249f1..ec3eef7 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ .rspec_status Gemfile.lock +/**/CLAUDE.md +mise.toml From 3c6983b5190505ece80a69245c2db5159b7d5037 Mon Sep 17 00:00:00 2001 From: Owaru Ryudo Date: Mon, 23 Feb 2026 12:05:47 +0800 Subject: [PATCH 12/12] Bump version to 0.14.0 Co-Authored-By: Claude Opus 4.6 --- lib/bankai/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bankai/version.rb b/lib/bankai/version.rb index 6c8fe07..c2755c7 100644 --- a/lib/bankai/version.rb +++ b/lib/bankai/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Bankai - VERSION = '0.13.4' + VERSION = '0.14.0' RAILS_VERSION = '7.0.0' RUBOCOP_VERSION = '1.24.1' CAPISTRANO_VERSION = '3.16.0'