From 9860cb992bbed2bdca1c2f55f6322293015d3fa5 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Thu, 20 Feb 2025 19:18:36 +0700 Subject: [PATCH 01/60] Revert "Drop MRI 1.8.7-2.2 support (#158)" This reverts commit 92d5134994003d6f17e874117483bac7e8fb7829. --- .github/workflows/main.yml | 18 ++- .rubocop.yml | 17 +++ .rubocop_gradual.lock | 111 ++++++++++++++++++ .tool-versions | 1 + Gemfile | 26 +++- Gemfile-1.8 | 6 + Gemfile-2.0 | 4 + Gemfile-2.1 | 4 + README.md | 28 ++--- Rakefile | 13 +- appraisal.gemspec | 59 +++++++--- bin/bundle | 30 +++-- exe/appraisal | 2 +- gemfiles/modular/style.gemfile | 12 ++ lib/appraisal/appraisal.rb | 28 ++--- lib/appraisal/appraisal_file.rb | 8 +- lib/appraisal/bundler_dsl.rb | 43 ++++--- lib/appraisal/cli.rb | 52 ++++---- lib/appraisal/command.rb | 22 ++-- lib/appraisal/customize.rb | 26 ++-- lib/appraisal/dependency.rb | 12 +- lib/appraisal/dependency_list.rb | 15 +-- lib/appraisal/gemfile.rb | 2 +- lib/appraisal/gemspec.rb | 2 +- lib/appraisal/git.rb | 4 +- lib/appraisal/group.rb | 12 +- lib/appraisal/ordered_hash.rb | 22 ++++ lib/appraisal/path.rb | 4 +- lib/appraisal/platform.rb | 12 +- lib/appraisal/source.rb | 12 +- lib/appraisal/task.rb | 50 ++++---- lib/appraisal/utils.rb | 26 ++-- ...als_file_bundler_dsl_compatibility_spec.rb | 22 +++- .../bundle_with_custom_path_spec.rb | 22 +++- spec/acceptance/bundle_without_spec.rb | 5 +- spec/acceptance/cli/install_spec.rb | 14 +-- spec/acceptance/cli/update_spec.rb | 4 +- spec/acceptance/gemspec_spec.rb | 9 +- spec/appraisal/appraisal_file_spec.rb | 14 +-- spec/appraisal/appraisal_spec.rb | 40 +++---- spec/appraisal/customize_spec.rb | 85 +++++++------- spec/appraisal/dependency_list_spec.rb | 4 +- spec/appraisal/gemfile_spec.rb | 107 ++++++++--------- spec/appraisal/utils_spec.rb | 39 +++--- spec/spec_helper.rb | 6 +- spec/support/acceptance_test_helpers.rb | 39 +++--- spec/support/dependency_helpers.rb | 49 ++++---- spec/support/stream_helpers.rb | 2 +- 48 files changed, 723 insertions(+), 421 deletions(-) create mode 100644 .rubocop.yml create mode 100644 .rubocop_gradual.lock create mode 100644 .tool-versions create mode 100644 Gemfile-1.8 create mode 100644 Gemfile-2.0 create mode 100644 Gemfile-2.1 create mode 100644 gemfiles/modular/style.gemfile create mode 100644 lib/appraisal/ordered_hash.rb diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2d43edaa..7e5742e3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,8 +40,24 @@ jobs: RUBY_VERSION: ${{ matrix.ruby }} run: | case ${RUBY_VERSION} in + 1.8|1.9|2.0|2.1|2.2) + gem install bundler -v 1.17.3 + ;; + + 2.3|2.4|2.5) + gem install bundler -v 2.3.27 + ;; + + 2.6|2.7) + gem install bundler -v 2.4.22 + ;; + + 3.0) + gem install bundler -v 2.5.23 + ;; + truffleruby|truffleruby-head) - gem install bundler -v 2.5.18 + gem install bundler -v 2.5.23 ;; *) diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..0d8799c6 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,17 @@ +inherit_gem: + rubocop-lts: config/rubygem_rspec.yml + +RSpec/ExampleLength: + Enabled: false + +RSpec/MultipleExpectations: + Enabled: false + +RSpec/DescribeClass: + Enabled: false + +# TODO: We would need to implement Mutexes in order to make violations thread safe. +# But even then they would still trigger the violation. +# See: https://coderscat.com/ruby-change-current-working-directory/ +ThreadSafety/DirChdir: + Enabled: false diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock new file mode 100644 index 00000000..94dc799e --- /dev/null +++ b/.rubocop_gradual.lock @@ -0,0 +1,111 @@ +{ + "Gemfile:3311641552": [ + [19, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [21, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [23, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] + ], + "bin/bundle:3123891436": [ + [66, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] + ], + "lib/appraisal/appraisal_file.rb:3486777149": [ + [13, 5, 52, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 946226050] + ], + "lib/appraisal/cli.rb:435288507": [ + [116, 5, 410, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 1969529734] + ], + "lib/appraisal/customize.rb:190316824": [ + [10, 5, 138, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2682968747], + [17, 5, 62, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 4082816720], + [21, 5, 516, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2780620929] + ], + "lib/appraisal/utils.rb:2308689703": [ + [6, 5, 129, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 733338411], + [13, 5, 354, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 119295155], + [35, 5, 152, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1306460482], + [42, 5, 151, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1120325158], + [48, 5, 97, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2744794681], + [52, 5, 244, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1461524090], + [61, 5, 111, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1909626476] + ], + "spec/acceptance/cli/clean_spec.rb:1398207731": [ + [5, 23, 17, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 1606893221] + ], + "spec/acceptance/cli/generate_spec.rb:1599585127": [ + [5, 23, 20, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3905826443] + ], + "spec/acceptance/cli/help_spec.rb:3832542771": [ + [5, 23, 16, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 2148351217] + ], + "spec/acceptance/cli/install_spec.rb:2827187127": [ + [5, 23, 19, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3284642881] + ], + "spec/acceptance/cli/list_spec.rb:1943273700": [ + [5, 23, 16, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 2152687586] + ], + "spec/acceptance/cli/update_spec.rb:2524405540": [ + [5, 23, 18, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3752509585] + ], + "spec/acceptance/cli/version_spec.rb:4076882072": [ + [5, 23, 19, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 316256858] + ], + "spec/appraisal/appraisal_file_spec.rb:1896479557": [ + [28, 18, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [33, 7, 57, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 511689843], + [41, 20, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [41, 33, 39, "RSpec/ExpectChange: Prefer `change(Appraisal::Customize, :heading)`.", 513325635], + [45, 7, 63, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1527582647], + [53, 20, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [53, 33, 45, "RSpec/ExpectChange: Prefer `change(Appraisal::Customize, :single_quotes)`.", 627072007], + [57, 7, 77, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1960750461], + [65, 11, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] + ], + "spec/appraisal/appraisal_spec.rb:1242607413": [ + [33, 11, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2511581329], + [90, 11, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1120511218], + [95, 7, 83, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [96].", 1453890366], + [95, 13, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [96, 7, 82, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [95].", 1614459968], + [96, 13, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [97, 61, 20, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 2281802167], + [104, 9, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [114, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [120, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [126, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192] + ], + "spec/appraisal/customize_spec.rb:1577209079": [ + [7, 1, 4439, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 3030165271], + [17, 3, 13, "RSpec/SubjectDeclaration: Use subject explicitly rather than using let", 3282510975], + [25, 3, 564, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 3336288078], + [27, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [43, 3, 286, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 4222920637], + [45, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [55, 3, 2985, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [13/5]", 1576524985], + [65, 7, 62, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [66, 67, 68].", 123979604], + [66, 7, 72, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 67, 68].", 3240119264], + [67, 7, 74, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 66, 68].", 3701550880], + [68, 7, 85, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 66, 67].", 3874694796], + [72, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] + ], + "spec/appraisal/gemfile_spec.rb:3323881535": [ + [227, 11, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3608128140], + [228, 13, 13, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 420381022], + [235, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3511037132], + [245, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3100155342], + [255, 11, 24, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3242693747], + [258, 13, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 105800534], + [281, 13, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 179066369], + [312, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3912615366], + [356, 13, 14, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2832187185], + [414, 13, 22, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 772581599], + [424, 11, 20, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1076107314] + ], + "spec/appraisal/utils_spec.rb:2286225770": [ + [62, 17, 58, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 1573223692] + ], + "spec/support/acceptance_test_helpers.rb:1261310616": [ + [133, 5, 32, "Style/InvertibleUnlessCondition: Prefer `if $?.exitstatus == 0` over `unless $?.exitstatus != 0`.", 4187517264] + ], + "spec/support/stream_helpers.rb:3273310040": [ + [9, 17, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] + ] +} diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..ae5ecdb2 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +ruby 3.4.2 diff --git a/Gemfile b/Gemfile index a0dda8f5..e73905ca 100644 --- a/Gemfile +++ b/Gemfile @@ -2,10 +2,30 @@ source "https://rubygems.org" gemspec +platform :mri do + # Debugging + gem "byebug", ">= 11" + + # Dev Console - Binding.pry - Irb replacement + gem "pry", "~> 0.14" # ruby >= 2.0 +end + # This here to make sure appraisal works with Rails 3.0.0. gem "thor", "~> 0.14.0" -group :development, :test do - gem "activesupport", ">= 3.2.21" - gem "rspec", "~> 3.0" +# Ruby version specific dependencies +ruby_version = Gem::Version.new(RUBY_VERSION) +if ruby_version < Gem::Version.new("1.9") + eval File.read("Gemfile-1.8") +elsif ruby_version < Gem::Version.new("2.1") + eval File.read("Gemfile-2.0") +elsif ruby_version < Gem::Version.new("2.2") + eval File.read("Gemfile-2.1") +elsif ruby_version < Gem::Version.new("2.7") + # Std Lib extractions + gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 +else + # Ruby >= 2.7 we can run style / lint checks via rubocop-gradual with rubocop-lts rules for Ruby 1.8+. + # This means we can develop on modern Ruby but remain compatible with ancient Ruby. + eval_gemfile "gemfiles/modular/style.gemfile" end diff --git a/Gemfile-1.8 b/Gemfile-1.8 new file mode 100644 index 00000000..976c8496 --- /dev/null +++ b/Gemfile-1.8 @@ -0,0 +1,6 @@ +# These gems are locked for Ruby 1.8.7 compatibility +gem "i18n", "~> 0.6.0" +gem "activesupport", "~> 3.2.21" +gem "rake", "~> 10.5" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.3" # Removed from Std Lib in Ruby 3.5 diff --git a/Gemfile-2.0 b/Gemfile-2.0 new file mode 100644 index 00000000..75ff4f5d --- /dev/null +++ b/Gemfile-2.0 @@ -0,0 +1,4 @@ +# These gems are locked for Ruby 1.9 & 2.0 compatibility +gem "activesupport", "~> 4.2.7" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.3" # Removed from Std Lib in Ruby 3.5 diff --git a/Gemfile-2.1 b/Gemfile-2.1 new file mode 100644 index 00000000..71901a8d --- /dev/null +++ b/Gemfile-2.1 @@ -0,0 +1,4 @@ +# These gems are locked for Ruby 2.1 compatibility +gem "activesupport", "~> 4.2.7" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 diff --git a/README.md b/README.md index 464f9165..aa2cfda0 100644 --- a/README.md +++ b/README.md @@ -122,31 +122,31 @@ To do this, use the `remove_gem` declaration within the necessary `appraise` blo **Gemfile** ```ruby -gem 'rails', '~> 4.2' +gem "rails", "~> 4.2" group :test do - gem 'rspec', '~> 4.0' - gem 'test_after_commit' + gem "rspec", "~> 4.0" + gem "test_after_commit" end ``` **Appraisals** ```ruby -appraise 'rails-5' do - gem 'rails', '~> 5.2' +appraise "rails-5" do + gem "rails", "~> 5.2" group :test do - remove_gem 'test_after_commit' + remove_gem "test_after_commit" end end ``` Using the `Appraisals` file defined above, this is what the resulting `Gemfile` will look like: ```ruby -gem 'rails', '~> 5.2' +gem "rails", "~> 5.2" group :test do - gem 'rspec', '~> 4.0' + gem "rspec", "~> 4.0" end ``` @@ -174,12 +174,12 @@ You can also provide variables for substitution in the heading, based on each ap ```ruby customize_gemfiles do { - single_quotes: true, - heading: <<~HEADING - frozen_string_literal: true + :single_quotes => true, + :heading => <<-HEADING, +frozen_string_literal: true - `%{gemfile}` has been generated by Appraisal, do NOT modify it or `%{lockfile}` directly! - Make the changes to the "%{appraisal}" block in `Appraisals` instead. See the conventions at https://example.com/ +`%{gemfile}` has been generated by Appraisal, do NOT modify it or `%{lockfile}` directly! +Make the changes to the "%{appraisal}" block in `Appraisals` instead. See the conventions at https://example.com/ HEADING } end @@ -196,7 +196,7 @@ Using the `Appraisals` file defined above, this is what the resulting `Gemfile` # `rails-3.gemfile` has been generated by Appraisal, do NOT modify it or `rails-3.gemfile.lock` directly! # Make the changes to the "rails-3" block in `Appraisals` instead. See the conventions at https://example.com/ -gem 'rails', '3.2.14' +gem "rails", "3.2.14" ``` Version Control diff --git a/Rakefile b/Rakefile index f8d79dbc..44f0463b 100644 --- a/Rakefile +++ b/Rakefile @@ -10,5 +10,14 @@ RSpec::Core::RakeTask.new do |t| t.verbose = false end -desc "Default: run the rspec examples" -task default: [:spec] +begin + require "rubocop/lts" + Rubocop::Lts.install_tasks +rescue LoadError + task(:rubocop_gradual) do + warn("RuboCop (Gradual) is disabled") + end +end + +desc "Default: rubocop_gradual's autocorrect and run the rspec examples" +task :default => ["rubocop_gradual:autocorrect", :spec] diff --git a/appraisal.gemspec b/appraisal.gemspec index d136a37f..6a037762 100644 --- a/appraisal.gemspec +++ b/appraisal.gemspec @@ -1,26 +1,51 @@ # frozen_string_literal: true -require_relative "lib/appraisal/version" +# TODO: Switch to require_relative once support for Ruby < 2 is dropped. +# require_relative "lib/appraisal/version" + +$:.push(File.expand_path("lib", __dir__)) +require "appraisal/version" Gem::Specification.new do |s| - s.name = "appraisal" - s.version = Appraisal::VERSION.dup - s.platform = Gem::Platform::RUBY - s.authors = ["Joe Ferris", "Prem Sichanugrist"] - s.email = ["jferris@thoughtbot.com", "prem@thoughtbot.com"] - s.homepage = "http://github.com/thoughtbot/appraisal" - s.summary = "Find out what your Ruby gems are worth" + s.name = "appraisal" + s.version = Appraisal::VERSION.dup + s.platform = Gem::Platform::RUBY + s.authors = ["Joe Ferris", "Prem Sichanugrist"] + s.email = ["jferris@thoughtbot.com", "prem@thoughtbot.com"] + s.homepage = "http://github.com/thoughtbot/appraisal" + s.summary = "Find out what your Ruby gems are worth" s.description = 'Appraisal integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."' - s.license = "MIT" + s.license = "MIT" + + # specify which files should be added to the gem when it is released. + s.files = Dir[ + # Splats (keep alphabetical) + "lib/**/*.rb", + ] + + # automatically included with gem package, no need to list twice (i.e. do not list in files above). + s.extra_rdoc_files = Dir[ + # Files (keep alphabetical) + "CONTRIBUTING.md", + "MIT-LICENSE", + "README.md", + "SECURITY.md", + ] + + # bin/ is scripts, in any available language, for development of this specific gem + # exe/ is for ruby scripts that will ship with this gem to be used by other tools + s.bindir = "exe" + # files listed are relative paths from bindir above. + s.executables = [ + "appraisal", + ] - s.files = `git ls-files`.split("\n") - s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") - s.executables = `git ls-files -- exe/*`.split("\n").map { |f| File.basename(f) } - s.bindir = "exe" + s.required_ruby_version = ">= 1.8.7" - s.required_ruby_version = ">= 2.3.0" + s.add_runtime_dependency("bundler", ">= 1.17.3") # Last version supporting Ruby 1.8.7 + s.add_runtime_dependency("rake", ">= 10") # Last version supporting Ruby 1.8.7 + s.add_runtime_dependency("thor", ">= 0.14.0") - s.add_dependency("rake") - s.add_dependency("bundler") - s.add_dependency("thor", ">= 0.14.0") + s.add_development_dependency("activesupport", ">= 3.2.21") + s.add_development_dependency("rspec", "~> 3.0") end diff --git a/bin/bundle b/bin/bundle index 50da5fdf..8f20a586 100755 --- a/bin/bundle +++ b/bin/bundle @@ -24,14 +24,14 @@ m = Module.new do def cli_arg_version return unless invoked_as_script? # don't want to hijack other binstubs return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` + bundler_version = nil update_index = nil ARGV.each_with_index do |a, i| - if update_index && update_index.succ == i && a.match?(Gem::Version::ANCHORED_VERSION_PATTERN) - bundler_version = a - end - next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ - bundler_version = $1 + bundler_version = a if update_index && update_index.succ == i && a.match?(Gem::Version::ANCHORED_VERSION_PATTERN) + next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/o + + bundler_version = Regexp.last_match(1) update_index = i end bundler_version @@ -55,8 +55,10 @@ m = Module.new do def lockfile_version return unless File.file?(lockfile) + lockfile_contents = File.read(lockfile) - return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ + return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/o + Regexp.last_match(1) end @@ -83,15 +85,19 @@ m = Module.new do def activate_bundler gem_error = activation_error_handling do - gem "bundler", bundler_requirement + gem("bundler", bundler_requirement) end return if gem_error.nil? + require_error = activation_error_handling do require "bundler/version" end - return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) - warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" - exit 42 + if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + return + end + + warn("Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`") + exit(42) end def activation_error_handling @@ -104,6 +110,4 @@ end m.load_bundler! -if m.invoked_as_script? - load Gem.bin_path("bundler", "bundle") -end +load Gem.bin_path("bundler", "bundle") if m.invoked_as_script? diff --git a/exe/appraisal b/exe/appraisal index 4e963840..16e4087a 100755 --- a/exe/appraisal +++ b/exe/appraisal @@ -10,5 +10,5 @@ begin Appraisal::CLI.start rescue Appraisal::AppraisalsNotFound => e puts e.message - exit 127 + exit(127) end diff --git a/gemfiles/modular/style.gemfile b/gemfiles/modular/style.gemfile new file mode 100644 index 00000000..c9cf8473 --- /dev/null +++ b/gemfiles/modular/style.gemfile @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# We run rubocop on the latest version of Ruby, +# but in support of the oldest supported version of Ruby + +gem "rubocop-lts", "~> 0.1", ">= 0.1.1" # Style and Linting support for Ruby >= 1.8 +gem "rubocop-packaging", "~> 0.5", ">= 0.5.2" +gem "rubocop-rspec", "~> 3.2" +gem "standard", ">= 1.35.1", "!= 1.41.1", "!= 1.42.0" + +# Std Lib extractions +gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 diff --git a/lib/appraisal/appraisal.rb b/lib/appraisal/appraisal.rb index 86f2c3eb..3d76c5a4 100644 --- a/lib/appraisal/appraisal.rb +++ b/lib/appraisal/appraisal.rb @@ -10,7 +10,7 @@ module Appraisal # Represents one appraisal and its dependencies class Appraisal - DEFAULT_INSTALL_OPTIONS = { "jobs" => 1 }.freeze + DEFAULT_INSTALL_OPTIONS = {"jobs" => 1}.freeze attr_reader :name, :gemfile @@ -74,28 +74,24 @@ def write_gemfile def install(options = {}) commands = [install_command(options).join(" ")] - if options["without"].nil? || options["without"].empty? - commands.unshift(check_command.join(" ")) - end + commands.unshift(check_command.join(" ")) if options["without"].nil? || options["without"].empty? command = commands.join(" || ") if Bundler.settings[:path] - env = { "BUNDLE_DISABLE_SHARED_GEMS" => "1" } - Command.new(command, env: env).run + env = {"BUNDLE_DISABLE_SHARED_GEMS" => "1"} + Command.new(command, :env => env).run else Command.new(command).run end end def update(gems = []) - Command.new(update_command(gems), gemfile: gemfile_path).run + Command.new(update_command(gems), :gemfile => gemfile_path).run end def gemfile_path - unless gemfile_root.exist? - gemfile_root.mkdir - end + gemfile_root.mkdir unless gemfile_root.exist? gemfile_root.join(gemfile_name).to_s end @@ -110,10 +106,10 @@ def relativize lockfile_content = File.read(lockfile_path) File.open(lockfile_path, "w") do |file| - file.write lockfile_content.gsub( + file.write(lockfile_content.gsub( / #{current_directory}/, - " #{relative_path}" - ) + " #{relative_path}", + )) end end @@ -150,7 +146,7 @@ def lockfile_path end def clean_name - name.gsub(/[^\w\.]/, "_") + name.gsub(/[^\w.]/, "_") end def bundle_options(options) @@ -161,8 +157,8 @@ def bundle_options(options) if Utils.support_parallel_installation? options_strings << "--jobs=#{jobs}" else - warn "Your current version of Bundler does not support parallel installation. Please " + - "upgrade Bundler to version >= 1.4.0, or invoke `appraisal` without `--jobs` option." + warn("Your current version of Bundler does not support parallel installation. Please " \ + "upgrade Bundler to version >= 1.4.0, or invoke `appraisal` without `--jobs` option.") end end diff --git a/lib/appraisal/appraisal_file.rb b/lib/appraisal/appraisal_file.rb index 2d182038..316673fb 100644 --- a/lib/appraisal/appraisal_file.rb +++ b/lib/appraisal/appraisal_file.rb @@ -19,11 +19,9 @@ def initialize @gemfile = Gemfile.new @gemfile.load(ENV["BUNDLE_GEMFILE"] || "Gemfile") - if File.exist? path - run IO.read(path) - else - raise AppraisalsNotFound - end + raise AppraisalsNotFound unless File.exist?(path) + + run(File.read(path)) end def each(&block) diff --git a/lib/appraisal/bundler_dsl.rb b/lib/appraisal/bundler_dsl.rb index e102f4cd..b3c87042 100644 --- a/lib/appraisal/bundler_dsl.rb +++ b/lib/appraisal/bundler_dsl.rb @@ -1,24 +1,35 @@ # frozen_string_literal: true require "appraisal/dependency_list" +require "appraisal/ordered_hash" module Appraisal class BundlerDSL attr_reader :dependencies - PARTS = %w[source ruby_version gits paths dependencies groups - platforms source_blocks install_if gemspec] + PARTS = %w[ + source + ruby_version + gits + paths + dependencies + groups + platforms + source_blocks + install_if + gemspec + ] def initialize @sources = [] @ruby_version = nil @dependencies = DependencyList.new @gemspecs = [] - @groups = {} - @platforms = {} - @gits = {} - @paths = {} - @source_blocks = {} + @groups = OrderedHash.new + @platforms = OrderedHash.new + @gits = OrderedHash.new + @paths = OrderedHash.new + @source_blocks = OrderedHash.new @git_sources = {} @install_if = {} end @@ -82,11 +93,11 @@ def path(source, options = {}, &block) end def to_s - Utils.join_parts(PARTS.map { |part| send("#{part}_entry") }) + Utils.join_parts(PARTS.map { |part| send(:"#{part}_entry") }) end def for_dup - Utils.join_parts(PARTS.map { |part| send("#{part}_entry_for_dup") }) + Utils.join_parts(PARTS.map { |part| send(:"#{part}_entry_for_dup") }) end def gemspec(options = {}) @@ -114,7 +125,7 @@ def ruby_version_entry case @ruby_version when String then "ruby #{@ruby_version.inspect}" - else "ruby(#{@ruby_version.inspect})" + else "ruby(#{Utils.format_string(@ruby_version)})" end end @@ -137,7 +148,7 @@ def dependencies_entry_for_dup end %i[gits paths platforms groups source_blocks install_if].each do |method_name| - class_eval <<-METHODS, __FILE__, __LINE__ + class_eval <<-METHODS, __FILE__, __LINE__ + 1 private def #{method_name}_entry @@ -156,11 +167,11 @@ def indent(string) def substitute_git_source(requirements) requirements.each do |requirement| - if requirement.is_a?(Hash) - (requirement.keys & @git_sources.keys).each do |matching_source| - value = requirement.delete(matching_source) - requirement[:git] = @git_sources[matching_source].call(value) - end + next unless requirement.is_a?(Hash) + + (requirement.keys & @git_sources.keys).each do |matching_source| + value = requirement.delete(matching_source) + requirement[:git] = @git_sources[matching_source].call(value) end end end diff --git a/lib/appraisal/cli.rb b/lib/appraisal/cli.rb index 3c8a56f1..f5a966a2 100644 --- a/lib/appraisal/cli.rb +++ b/lib/appraisal/cli.rb @@ -11,7 +11,7 @@ class CLI < Thor class << self # Override help command to print out usage def help(shell, subcommand = false) - shell.say strip_heredoc(<<-HELP) + shell.say(strip_heredoc(<<-HELP)) Appraisal: Find out what your Ruby gems are worth. Usage: @@ -23,10 +23,10 @@ def help(shell, subcommand = false) if File.exist?("Appraisals") shell.say - shell.say "Available Appraisal(s):" + shell.say("Available Appraisal(s):") AppraisalFile.each do |appraisal| - shell.say " - #{appraisal.name}" + shell.say(" - #{appraisal.name}") end end @@ -48,23 +48,31 @@ def strip_heredoc(string) end desc "install", "Resolve and install dependencies for each appraisal" - method_option "jobs", aliases: "j", type: :numeric, default: 1, - banner: "SIZE", - desc: "Install gems in parallel using the given number of workers." - method_option "retry", type: :numeric, default: 1, - desc: "Retry network and git requests that have failed" - method_option "without", banner: "GROUP_NAMES", - desc: "A space-separated list of groups referencing gems to skip " + + method_option "jobs", + :aliases => "j", + :type => :numeric, + :default => 1, + :banner => "SIZE", + :desc => "Install gems in parallel using the given number of workers." + method_option "retry", + :type => :numeric, + :default => 1, + :desc => "Retry network and git requests that have failed" + method_option "without", + :banner => "GROUP_NAMES", + :desc => "A space-separated list of groups referencing gems to skip " \ "during installation. Bundler will remember this option." - method_option "full-index", type: :boolean, - desc: "Run bundle install with the " \ - "full-index argument." - method_option "path", type: :string, - desc: "Install gems in the specified directory. " \ - "Bundler will remember this option." + method_option "full-index", + :type => :boolean, + :desc => "Run bundle install with the " \ + "full-index argument." + method_option "path", + :type => :string, + :desc => "Install gems in the specified directory. " \ + "Bundler will remember this option." def install - invoke :generate, [], {} + invoke(:generate, [], {}) AppraisalFile.each do |appraisal| appraisal.install(options) @@ -81,12 +89,12 @@ def generate desc "clean", "Remove all generated gemfiles and lockfiles from gemfiles folder" def clean - FileUtils.rm_f Dir["gemfiles/*.{gemfile,gemfile.lock}"] + FileUtils.rm_f(Dir["gemfiles/*.{gemfile,gemfile.lock}"]) end desc "update [LIST_OF_GEMS]", "Remove all generated gemfiles and lockfiles, resolve, and install dependencies again" def update(*gems) - invoke :generate, [] + invoke(:generate, []) AppraisalFile.each do |appraisal| appraisal.update(gems) @@ -105,16 +113,16 @@ def version private - def method_missing(name, *args, &block) + def method_missing(name, *args) matching_appraisal = AppraisalFile.new.appraisals.detect do |appraisal| appraisal.name == name.to_s end if matching_appraisal - Command.new(args, gemfile: matching_appraisal.gemfile_path).run + Command.new(args, :gemfile => matching_appraisal.gemfile_path).run else AppraisalFile.each do |appraisal| - Command.new(ARGV, gemfile: appraisal.gemfile_path).run + Command.new(ARGV, :gemfile => appraisal.gemfile_path).run end end end diff --git a/lib/appraisal/command.rb b/lib/appraisal/command.rb index facadfd9..76ac69f2 100644 --- a/lib/appraisal/command.rb +++ b/lib/appraisal/command.rb @@ -26,9 +26,7 @@ def run ENV[key] = value end - unless Kernel.system(command_as_string) - exit(1) - end + exit(1) unless Kernel.system(command_as_string) end end @@ -36,20 +34,20 @@ def run def ensure_bundler_is_available version = Utils.bundler_version - unless system %(gem list --silent -i bundler -v #{version}) - puts ">> Reinstall Bundler into #{ENV["GEM_HOME"]}" + return if system(%(gem list --silent -i bundler -v #{version})) + + puts ">> Reinstall Bundler into #{ENV["GEM_HOME"]}" + + return if system("gem install bundler --version #{version}") - unless system "gem install bundler --version #{version}" - puts - puts <<-ERROR.strip.gsub(/\s+/, " ") + puts + puts <<-ERROR.strip.gsub(/\s+/, " ") Bundler installation failed. Please try running: `GEM_HOME="#{ENV["GEM_HOME"]}" gem install bundler --version #{version}` manually. - ERROR - exit(1) - end - end + ERROR + exit(1) end def announce diff --git a/lib/appraisal/customize.rb b/lib/appraisal/customize.rb index 20cb99ac..8d9e4a75 100644 --- a/lib/appraisal/customize.rb +++ b/lib/appraisal/customize.rb @@ -3,12 +3,14 @@ module Appraisal class Customize def initialize(heading: nil, single_quotes: false) - @@heading = heading&.chomp + @@heading = !heading.nil? && heading.chomp @@single_quotes = single_quotes end - def self.heading(gemfile) + def self.heading(gemfile = nil) @@heading ||= nil + return @@heading unless gemfile + customize(@@heading, gemfile) end @@ -16,18 +18,18 @@ def self.single_quotes @@single_quotes ||= false end - def self.customize(heading, gemfile) - return nil unless heading + def self.customize(topper, gemfile) + return unless topper format( - heading.to_s, - appraisal: gemfile.send("clean_name"), - gemfile: gemfile.send("gemfile_name"), - gemfile_path: gemfile.gemfile_path, - lockfile: "#{gemfile.send('gemfile_name')}.lock", - lockfile_path: gemfile.send("lockfile_path"), - relative_gemfile_path: gemfile.relative_gemfile_path, - relative_lockfile_path: "#{gemfile.relative_gemfile_path}.lock" + topper.to_s, + :appraisal => gemfile.send(:clean_name), + :gemfile => gemfile.send(:gemfile_name), + :gemfile_path => gemfile.gemfile_path, + :lockfile => "#{gemfile.send(:gemfile_name)}.lock", + :lockfile_path => gemfile.send(:lockfile_path), + :relative_gemfile_path => gemfile.relative_gemfile_path, + :relative_lockfile_path => "#{gemfile.relative_gemfile_path}.lock", ) end diff --git a/lib/appraisal/dependency.rb b/lib/appraisal/dependency.rb index 37302ab8..367749df 100644 --- a/lib/appraisal/dependency.rb +++ b/lib/appraisal/dependency.rb @@ -14,12 +14,12 @@ def initialize(name, requirements) end def to_s - formatted_output Utils.format_arguments(path_prefixed_requirements) + formatted_output(Utils.format_arguments(path_prefixed_requirements)) end # :nodoc: def for_dup - formatted_output Utils.format_arguments(requirements) + formatted_output(Utils.format_arguments(requirements)) end private @@ -27,13 +27,9 @@ def for_dup def path_prefixed_requirements requirements.map do |requirement| if requirement.is_a?(Hash) - if requirement[:path] - requirement[:path] = Utils.prefix_path(requirement[:path]) - end + requirement[:path] = Utils.prefix_path(requirement[:path]) if requirement[:path] - if requirement[:git] - requirement[:git] = Utils.prefix_path(requirement[:git]) - end + requirement[:git] = Utils.prefix_path(requirement[:git]) if requirement[:git] end requirement diff --git a/lib/appraisal/dependency_list.rb b/lib/appraisal/dependency_list.rb index 9b6fb8d9..8a42c938 100644 --- a/lib/appraisal/dependency_list.rb +++ b/lib/appraisal/dependency_list.rb @@ -1,25 +1,26 @@ # frozen_string_literal: true require "appraisal/dependency" +require "appraisal/ordered_hash" require "set" module Appraisal class DependencyList def initialize - @dependencies = {} + @dependencies = OrderedHash.new @removed_dependencies = Set.new end def add(name, requirements) - unless @removed_dependencies.include?(name) - @dependencies[name] = Dependency.new(name, requirements) - end + return if @removed_dependencies.include?(name) + + @dependencies[name] = Dependency.new(name, requirements) end def remove(name) - if @removed_dependencies.add?(name) - @dependencies.delete(name) - end + return unless @removed_dependencies.add?(name) + + @dependencies.delete(name) end def to_s diff --git a/lib/appraisal/gemfile.rb b/lib/appraisal/gemfile.rb index bfbb4580..93911b57 100644 --- a/lib/appraisal/gemfile.rb +++ b/lib/appraisal/gemfile.rb @@ -14,7 +14,7 @@ module Appraisal # Load bundler Gemfiles and merge dependencies class Gemfile < BundlerDSL def load(path) - run(IO.read(path), path) if File.exist?(path) + run(File.read(path), path) if File.exist?(path) end def run(definitions, path, line = 1) diff --git a/lib/appraisal/gemspec.rb b/lib/appraisal/gemspec.rb index 8c4d6a0a..dfdef6de 100644 --- a/lib/appraisal/gemspec.rb +++ b/lib/appraisal/gemspec.rb @@ -24,7 +24,7 @@ def for_dup def exported_options @options.merge( - path: Utils.prefix_path(@options[:path]) + :path => Utils.prefix_path(@options[:path]), ) end end diff --git a/lib/appraisal/git.rb b/lib/appraisal/git.rb index 5849cca1..791429df 100644 --- a/lib/appraisal/git.rb +++ b/lib/appraisal/git.rb @@ -15,7 +15,7 @@ def to_s if @options.empty? "git #{Utils.prefix_path(@source).inspect} do\n#{indent(super)}\nend" else - "git #{Utils.prefix_path(@source).inspect}, #{Utils.format_string(@options)} do\n" + + "git #{Utils.prefix_path(@source).inspect}, #{Utils.format_string(@options)} do\n" \ "#{indent(super)}\nend" end end @@ -25,7 +25,7 @@ def for_dup if @options.empty? "git #{@source.inspect} do\n#{indent(super)}\nend" else - "git #{@source.inspect}, #{Utils.format_string(@options)} do\n" + + "git #{@source.inspect}, #{Utils.format_string(@options)} do\n" \ "#{indent(super)}\nend" end end diff --git a/lib/appraisal/group.rb b/lib/appraisal/group.rb index 2327298c..50351a88 100644 --- a/lib/appraisal/group.rb +++ b/lib/appraisal/group.rb @@ -11,21 +11,21 @@ def initialize(group_names) end def to_s - formatted_output indent(super) + formatted_output(indent(super)) end # :nodoc: def for_dup - formatted_output indent(super) + formatted_output(indent(super)) end private def formatted_output(output_dependencies) - <<~OUTPUT.strip - group #{Utils.format_arguments(@group_names)} do - #{output_dependencies} - end + <<-OUTPUT.strip +group #{Utils.format_arguments(@group_names)} do +#{output_dependencies} +end OUTPUT end end diff --git a/lib/appraisal/ordered_hash.rb b/lib/appraisal/ordered_hash.rb new file mode 100644 index 00000000..b460f9d5 --- /dev/null +++ b/lib/appraisal/ordered_hash.rb @@ -0,0 +1,22 @@ +module Appraisal + # An ordered hash implementation for Ruby 1.8.7 compatibility. This is not + # a complete implementation, but it covers Appraisal's specific needs. + class OrderedHash < ::Hash + # Hashes are ordered in Ruby 1.9. + if RUBY_VERSION < "1.9" + def initialize(*args, &block) + super + @keys = [] + end + + def []=(key, value) + @keys << key unless has_key?(key) + super + end + + def values + @keys.collect { |key| self[key] } + end + end + end +end diff --git a/lib/appraisal/path.rb b/lib/appraisal/path.rb index f06d2737..c33b60c6 100644 --- a/lib/appraisal/path.rb +++ b/lib/appraisal/path.rb @@ -15,7 +15,7 @@ def to_s if @options.empty? "path #{Utils.prefix_path(@source).inspect} do\n#{indent(super)}\nend" else - "path #{Utils.prefix_path(@source).inspect}, #{Utils.format_string(@options)} do\n" + + "path #{Utils.prefix_path(@source).inspect}, #{Utils.format_string(@options)} do\n" \ "#{indent(super)}\nend" end end @@ -25,7 +25,7 @@ def for_dup if @options.empty? "path #{@source.inspect} do\n#{indent(super)}\nend" else - "path #{@source.inspect}, #{Utils.format_string(@options)} do\n" + + "path #{@source.inspect}, #{Utils.format_string(@options)} do\n" \ "#{indent(super)}\nend" end end diff --git a/lib/appraisal/platform.rb b/lib/appraisal/platform.rb index ad98ce1f..ae0e0849 100644 --- a/lib/appraisal/platform.rb +++ b/lib/appraisal/platform.rb @@ -11,21 +11,21 @@ def initialize(platform_names) end def to_s - formatted_output indent(super) + formatted_output(indent(super)) end # :nodoc: def for_dup - formatted_output indent(super) + formatted_output(indent(super)) end private def formatted_output(output_dependencies) - <<~OUTPUT.strip - platforms #{Utils.format_arguments(@platform_names)} do - #{output_dependencies} - end + <<-OUTPUT.strip +platforms #{Utils.format_arguments(@platform_names)} do +#{output_dependencies} +end OUTPUT end end diff --git a/lib/appraisal/source.rb b/lib/appraisal/source.rb index c5905617..ebbe71e9 100644 --- a/lib/appraisal/source.rb +++ b/lib/appraisal/source.rb @@ -11,21 +11,21 @@ def initialize(source) end def to_s - formatted_output indent(super) + formatted_output(indent(super)) end # :nodoc: def for_dup - formatted_output indent(super) + formatted_output(indent(super)) end private def formatted_output(output_dependencies) - <<~OUTPUT.strip - source #{@source.inspect} do - #{output_dependencies} - end + <<-OUTPUT.strip +source #{@source.inspect} do +#{output_dependencies} +end OUTPUT end end diff --git a/lib/appraisal/task.rb b/lib/appraisal/task.rb index 5c649925..cdca7b3d 100644 --- a/lib/appraisal/task.rb +++ b/lib/appraisal/task.rb @@ -8,49 +8,49 @@ module Appraisal # for a given appraisal. class Task < Rake::TaskLib def initialize - namespace :appraisal do - desc "DEPRECATED: Generate a Gemfile for each appraisal" - task :gemfiles do - warn "`rake appraisal:gemfile` task is deprecated and will be removed soon. " + - "Please use `appraisal generate`." - exec "bundle exec appraisal generate" + namespace(:appraisal) do + desc("DEPRECATED: Generate a Gemfile for each appraisal") + task(:gemfiles) do + warn("`rake appraisal:gemfile` task is deprecated and will be removed soon. " \ + "Please use `appraisal generate`.") + exec("bundle exec appraisal generate") end - desc "DEPRECATED: Resolve and install dependencies for each appraisal" - task :install do - warn "`rake appraisal:install` task is deprecated and will be removed soon. " + - "Please use `appraisal install`." - exec "bundle exec appraisal install" + desc("DEPRECATED: Resolve and install dependencies for each appraisal") + task(:install) do + warn("`rake appraisal:install` task is deprecated and will be removed soon. " \ + "Please use `appraisal install`.") + exec("bundle exec appraisal install") end - desc "DEPRECATED: Remove all generated gemfiles from gemfiles/ folder" - task :cleanup do - warn "`rake appraisal:cleanup` task is deprecated and will be removed soon. " + - "Please use `appraisal clean`." - exec "bundle exec appraisal clean" + desc("DEPRECATED: Remove all generated gemfiles from gemfiles/ folder") + task(:cleanup) do + warn("`rake appraisal:cleanup` task is deprecated and will be removed soon. " \ + "Please use `appraisal clean`.") + exec("bundle exec appraisal clean") end begin AppraisalFile.each do |appraisal| - desc "DEPRECATED: Run the given task for appraisal #{appraisal.name}" - task appraisal.name do + desc("DEPRECATED: Run the given task for appraisal #{appraisal.name}") + task(appraisal.name) do ARGV.shift - warn "`rake appraisal:#{appraisal.name}` task is deprecated and will be removed soon. " + - "Please use `appraisal #{appraisal.name} rake #{ARGV.join(' ')}`." - exec "bundle exec appraisal #{appraisal.name} rake #{ARGV.join(' ')}" + warn("`rake appraisal:#{appraisal.name}` task is deprecated and will be removed soon. " \ + "Please use `appraisal #{appraisal.name} rake #{ARGV.join(" ")}`.") + exec("bundle exec appraisal #{appraisal.name} rake #{ARGV.join(" ")}") end end rescue AppraisalsNotFound end - task :all do + task(:all) do ARGV.shift - exec "bundle exec appraisal rake #{ARGV.join(' ')}" + exec("bundle exec appraisal rake #{ARGV.join(" ")}") end end - desc "Run the given task for all appraisals" - task appraisal: "appraisal:all" + desc("Run the given task for all appraisals") + task(:appraisal => "appraisal:all") end end end diff --git a/lib/appraisal/utils.rb b/lib/appraisal/utils.rb index 40e6c31e..a9cf68e0 100644 --- a/lib/appraisal/utils.rb +++ b/lib/appraisal/utils.rb @@ -7,6 +7,9 @@ def self.support_parallel_installation? Gem::Version.create(Bundler::VERSION) >= Gem::Version.create("1.4.0.pre.1") end + # Appraisal needs to print Gemfiles in the oldest Ruby syntax that is supported by Appraisal. + # Otherwise, a project would not be able to use Appraisal to test compatibility + # with older versions of Ruby, which is a core use case for Appraisal. def self.format_string(object, enclosing_object = false) case object when Hash @@ -15,7 +18,7 @@ def self.format_string(object, enclosing_object = false) end if enclosing_object - "{ #{items.join(', ')} }" + "{ #{items.join(", ")} }" else items.join(", ") end @@ -24,21 +27,22 @@ def self.format_string(object, enclosing_object = false) end end + # Appraisal needs to print Gemfiles in the oldest Ruby syntax that is supported by Appraisal. + # This means formatting Hashes as Rockets, until support for Ruby 1.8 is dropped. + # Regardless of what Ruby is used to generate appraisals, + # generated appraisals may need to run on a different Ruby version. + # Generated appraisals should use a syntax compliant with the oldest supported Ruby version. def self.format_hash_value(key, value) key = format_string(key, true) value = format_string(value, true) - if key.start_with?(":") - "#{key.sub(/^:/, "")}: #{value}" - else - "#{key} => #{value}" - end + "#{key} => #{value}" end def self.format_arguments(arguments) - unless arguments.empty? - arguments.map { |object| format_string(object, false) }.join(", ") - end + return if arguments.empty? + + arguments.map { |object| format_string(object, false) }.join(", ") end def self.join_parts(parts) @@ -46,8 +50,8 @@ def self.join_parts(parts) end def self.prefix_path(path) - if path !~ /^(?:\/|\S:)/ && path !~ /^\S+:\/\// && path !~ /^\S+@\S+:/ - cleaned_path = path.gsub(/(^|\/)\.(?:\/|$)/, "\\1") + if path !~ %r{^(?:/|\S:)} && path !~ %r{^\S+://} && path !~ /^\S+@\S+:/ + cleaned_path = path.gsub(%r{(^|/)\.(?:/|$)}, '\\1') File.join("..", cleaned_path) else path diff --git a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb index 41e6cdd6..b5a46e6b 100644 --- a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb +++ b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb @@ -4,8 +4,18 @@ RSpec.describe "Appraisals file Bundler DSL compatibility" do it "supports all Bundler DSL in Appraisals file" do - build_gems %w[bagel orange_juice milk waffle coffee ham - sausage pancake rotten_egg mayonnaise] + build_gems %w[ + bagel + orange_juice + milk + waffle + coffee + ham + sausage + pancake + rotten_egg + mayonnaise + ] build_git_gems %w[egg croissant pain_au_chocolat omelette] build_gemfile <<-GEMFILE @@ -52,7 +62,7 @@ build_appraisal_file <<-APPRAISALS appraise 'breakfast' do source 'http://some-other-source.com' - ruby "2.3.0" + ruby "1.8.7" gem 'bread' gem "pain_au_chocolat", :custom_git_source => "pain_au_chocolat" @@ -100,7 +110,7 @@ source "https://rubygems.org" source "http://some-other-source.com" - ruby "2.3.0" + ruby "1.8.7" git "../../build/egg" do gem "egg" @@ -163,7 +173,7 @@ build_appraisal_file <<-APPRAISALS appraise 'ruby-version' do - ruby file: ".ruby-version" + ruby({:file => ".ruby-version"}) end APPRAISALS @@ -175,7 +185,7 @@ source "https://rubygems.org" - ruby({:file=>".ruby-version"}) + ruby(:file => ".ruby-version") gem "appraisal", :path => #{PROJECT_ROOT.inspect} GEMFILE diff --git a/spec/acceptance/bundle_with_custom_path_spec.rb b/spec/acceptance/bundle_with_custom_path_spec.rb index b0d2157b..cdb92c0a 100644 --- a/spec/acceptance/bundle_with_custom_path_spec.rb +++ b/spec/acceptance/bundle_with_custom_path_spec.rb @@ -6,12 +6,18 @@ let(:gem_name) { "rack" } let(:path) { "vendor/bundle" } - shared_examples :gemfile_dependencies_are_satisfied do + shared_examples "gemfile dependencies are satisfied" do it "installs gems in the --path directory" do build_gemfile <<-GEMFILE source "https://rubygems.org" gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + + if RUBY_VERSION < "1.9" + #{File.read(File.join(PROJECT_ROOT, "Gemfile-1.8"))} + elsif RUBY_VERSION < "2.2" + #{File.read(File.join(PROJECT_ROOT, "Gemfile-2.1"))} + end GEMFILE build_appraisal_file <<-APPRAISALS @@ -25,8 +31,8 @@ run "bundle exec appraisal install" installed_gem = Dir.glob("tmp/stage/#{path}/#{Gem.ruby_engine}/*/gems/*") - .map { |path| path.split("/").last } - .select { |gem| gem.include?(gem_name) } + .map { |path| path.split("/").last } + .select { |gem| gem.include?(gem_name) } expect(installed_gem).not_to be_empty bundle_output = run "bundle check" @@ -39,14 +45,18 @@ end end - include_examples :gemfile_dependencies_are_satisfied + include_examples "gemfile dependencies are satisfied" context "when already installed in vendor/another" do before do build_gemfile <<-GEMFILE source "https://rubygems.org" - gem '#{gem_name}' + if RUBY_VERSION <= "1.9" + gem '#{gem_name}', '~> 1.6.5' + else + gem '#{gem_name}' + end GEMFILE run "bundle config set --local path vendor/another" @@ -54,6 +64,6 @@ run "bundle config unset --local path" end - include_examples :gemfile_dependencies_are_satisfied + include_examples "gemfile dependencies are satisfied" end end diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index 7eb1b71f..9ee14737 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -2,8 +2,9 @@ require "spec_helper" -RSpec.describe "Bundler without flag" do - it "passes --without flag to Bundler on install" do +RSpec.describe "Bundle without group" do + it "config set --local without group is honored by Bundler" do + pending "config set --local without group support seems broken, see: https://github.com/rubygems/rubygems/issues/8518" build_gems %w[pancake orange_juice waffle coffee sausage soda] build_gemfile <<-GEMFILE diff --git a/spec/acceptance/cli/install_spec.rb b/spec/acceptance/cli/install_spec.rb index 09dcc106..1e93029f 100644 --- a/spec/acceptance/cli/install_spec.rb +++ b/spec/acceptance/cli/install_spec.rb @@ -60,7 +60,7 @@ expect(content_of("gemfiles/1.0.0.gemfile.lock")).to include("file://#{uri_dummy_path}") end - context "with job size", parallel: true do + context "with job size", :parallel do before do build_appraisal_file <<-APPRAISAL appraise '1.0.0' do @@ -72,15 +72,15 @@ it "accepts --jobs option to set job size" do output = run "appraisal install --jobs=2" - expect(output).to include("bundle install --gemfile='#{file('gemfiles/1.0.0.gemfile')}' --jobs=2") + expect(output).to include("bundle install --gemfile='#{file("gemfiles/1.0.0.gemfile")}' --jobs=2") end it "ignores --jobs option if the job size is less than or equal to 1" do output = run "appraisal install --jobs=0" - expect(output).to include("bundle install --gemfile='#{file('gemfiles/1.0.0.gemfile')}'") - expect(output).not_to include("bundle install --gemfile='#{file('gemfiles/1.0.0.gemfile')}' --jobs=0") - expect(output).not_to include("bundle install --gemfile='#{file('gemfiles/1.0.0.gemfile')}' --jobs=1") + expect(output).to include("bundle install --gemfile='#{file("gemfiles/1.0.0.gemfile")}'") + expect(output).not_to include("bundle install --gemfile='#{file("gemfiles/1.0.0.gemfile")}' --jobs=0") + expect(output).not_to include("bundle install --gemfile='#{file("gemfiles/1.0.0.gemfile")}' --jobs=1") end end @@ -96,7 +96,7 @@ it "accepts --full-index option to pull the full RubyGems index" do output = run("appraisal install --full-index") - expect(output).to include("bundle install --gemfile='#{file('gemfiles/1.0.0.gemfile')}' --retry 1 --full-index true") + expect(output).to include("bundle install --gemfile='#{file("gemfiles/1.0.0.gemfile")}' --retry 1 --full-index true") end end @@ -112,7 +112,7 @@ it "accepts --path option to specify the location to install gems into" do output = run("appraisal install --path vendor/appraisal") - expect(output).to include("bundle install --gemfile='#{file('gemfiles/1.0.0.gemfile')}' --path #{file('vendor/appraisal')} --retry 1") + expect(output).to include("bundle install --gemfile='#{file("gemfiles/1.0.0.gemfile")}' --path #{file("vendor/appraisal")} --retry 1") end end end diff --git a/spec/acceptance/cli/update_spec.rb b/spec/acceptance/cli/update_spec.rb index 8929c89c..3819a81c 100644 --- a/spec/acceptance/cli/update_spec.rb +++ b/spec/acceptance/cli/update_spec.rb @@ -20,8 +20,8 @@ after do in_test_directory do - `gem uninstall dummy -v 1.0.1` - `gem uninstall dummy2 -a` + %x{gem uninstall dummy -v 1.0.1} + %x{gem uninstall dummy2 -a} end end diff --git a/spec/acceptance/gemspec_spec.rb b/spec/acceptance/gemspec_spec.rb index d85fdf08..fd93a11d 100644 --- a/spec/acceptance/gemspec_spec.rb +++ b/spec/acceptance/gemspec_spec.rb @@ -45,11 +45,12 @@ end def build_appraisal_file - super <<-APPRAISALS + appraisals = <<-APPRAISALS appraise 'stock' do gem 'rake' end APPRAISALS + super(appraisals) end def build_rakefile @@ -66,7 +67,11 @@ def build_rakefile end def build_gemspec(path = ".") - Dir.mkdir("tmp/stage/#{path}") rescue nil + begin + Dir.mkdir("tmp/stage/#{path}") + rescue StandardError + nil + end write_file File.join(path, "gemspec_project.gemspec"), <<-GEMSPEC Gem::Specification.new do |s| diff --git a/spec/appraisal/appraisal_file_spec.rb b/spec/appraisal/appraisal_file_spec.rb index 8b583ea8..c90a390a 100644 --- a/spec/appraisal/appraisal_file_spec.rb +++ b/spec/appraisal/appraisal_file_spec.rb @@ -16,7 +16,7 @@ end describe "#customize_gemfiles" do - before(:each) do + before do allow(File).to receive(:exist?).with(anything).and_return(true) allow(IO).to receive(:read).with(anything).and_return("") end @@ -33,13 +33,11 @@ context "when the block returns a hash with :heading key" do subject do described_class.new.customize_gemfiles do - { heading: "foo" } + {:heading => "foo"} end end it "sets the heading" do - pending("test is broken: wrong number of arguments (given 0, expected 1)") - expect { subject }.to change { Appraisal::Customize.heading }.to("foo") end end @@ -47,7 +45,7 @@ context "when the block returns a hash with :single_quotes key" do subject do described_class.new.customize_gemfiles do - { single_quotes: true } + {:single_quotes => true} end end @@ -59,16 +57,14 @@ context "when the block returns a hash with :heading and :single_quotes keys" do subject do described_class.new.customize_gemfiles do - { heading: "foo", single_quotes: true } + {:heading => "foo", :single_quotes => true} end end it "sets the heading and single_quotes" do - pending("test is broken: wrong number of arguments (given 0, expected 1)") - subject expect(Appraisal::Customize.heading).to eq("foo") - expect(Appraisal::Customize.single_quotes).to eq(true) + expect(Appraisal::Customize.single_quotes).to be(true) end end end diff --git a/spec/appraisal/appraisal_spec.rb b/spec/appraisal/appraisal_spec.rb index d68bfd57..031c871e 100644 --- a/spec/appraisal/appraisal_spec.rb +++ b/spec/appraisal/appraisal_spec.rb @@ -6,23 +6,23 @@ RSpec.describe Appraisal::Appraisal do it "converts spaces to underscores in the gemfile path" do - appraisal = Appraisal::Appraisal.new("one two", "Gemfile") + appraisal = described_class.new("one two", "Gemfile") expect(appraisal.gemfile_path).to match(/one_two\.gemfile$/) end - it "converts punctuation to underscores in the gemfile path" do - appraisal = Appraisal::Appraisal.new("o&ne!", "Gemfile") + it "converts punctuation to underscores in the gemfile path" do + appraisal = described_class.new("o&ne!", "Gemfile") expect(appraisal.gemfile_path).to match(/o_ne_\.gemfile$/) end it "keeps dots in the gemfile path" do - appraisal = Appraisal::Appraisal.new("rails3.0", "Gemfile") + appraisal = described_class.new("rails3.0", "Gemfile") expect(appraisal.gemfile_path).to match(/rails3\.0\.gemfile$/) end it "generates a gemfile with a newline at the end of file" do output_file = Tempfile.new("gemfile") - appraisal = Appraisal::Appraisal.new("fake", "fake") + appraisal = described_class.new("fake", "fake") allow(appraisal).to receive(:gemfile_path).and_return(output_file.path) appraisal.write_gemfile @@ -33,9 +33,9 @@ context "gemfile customization" do it "generates a gemfile with a custom heading" do heading = "This file was generated with a custom heading!" - Appraisal::Customize.new(heading: heading) + Appraisal::Customize.new(:heading => heading) output_file = Tempfile.new("gemfile") - appraisal = Appraisal::Appraisal.new("custom", "Gemfile") + appraisal = described_class.new("custom", "Gemfile") allow(appraisal).to receive(:gemfile_path).and_return(output_file.path) appraisal.write_gemfile @@ -45,28 +45,28 @@ end it "generates a gemfile with multiple lines of custom heading" do - heading = <<~HEADING - frozen_string_literal: true\n - This file was generated with a custom heading! + heading = <<-HEADING +frozen_string_literal: true\n +This file was generated with a custom heading! HEADING - Appraisal::Customize.new(heading: heading) + Appraisal::Customize.new(:heading => heading) output_file = Tempfile.new("gemfile") - appraisal = Appraisal::Appraisal.new("custom", "Gemfile") + appraisal = described_class.new("custom", "Gemfile") allow(appraisal).to receive(:gemfile_path).and_return(output_file.path) appraisal.write_gemfile - expected_output = <<~HEADING - # frozen_string_literal: true\n - # This file was generated with a custom heading! + expected_output = <<-HEADING +# frozen_string_literal: true\n +# This file was generated with a custom heading! HEADING expect(output_file.read).to start_with(expected_output) end it "generates a gemfile with single quotes rather than doubles" do - Appraisal::Customize.new(single_quotes: true) + Appraisal::Customize.new(:single_quotes => true) output_file = Tempfile.new("gemfile") - appraisal = Appraisal::Appraisal.new("quotes", 'gem "foo"') + appraisal = described_class.new("quotes", 'gem "foo"') allow(appraisal).to receive(:gemfile_path).and_return(output_file.path) appraisal.write_gemfile @@ -77,7 +77,7 @@ it "does not customize anything by default" do Appraisal::Customize.new output_file = Tempfile.new("gemfile") - appraisal = Appraisal::Appraisal.new("fake", 'gem "foo"') + appraisal = described_class.new("fake", 'gem "foo"') allow(appraisal).to receive(:gemfile_path).and_return(output_file.path) appraisal.write_gemfile @@ -91,10 +91,10 @@ include StreamHelpers before do - @appraisal = Appraisal::Appraisal.new("fake", "fake") + @appraisal = described_class.new("fake", "fake") allow(@appraisal).to receive(:gemfile_path).and_return("/home/test/test directory") allow(@appraisal).to receive(:project_root).and_return(Pathname.new("/home/test")) - allow(Appraisal::Command).to receive(:new).and_return(double(run: true)) + allow(Appraisal::Command).to receive(:new).and_return(double(:run => true)) end it "runs single install command on Bundler < 1.4.0" do diff --git a/spec/appraisal/customize_spec.rb b/spec/appraisal/customize_spec.rb index 98e77f36..cc9e50f8 100644 --- a/spec/appraisal/customize_spec.rb +++ b/spec/appraisal/customize_spec.rb @@ -8,24 +8,24 @@ let(:appraisal) { Appraisal::Appraisal.new("test", "Gemfile") } let(:single_line_heading) { "This file was generated with a custom heading!" } let(:multi_line_heading) do - <<~HEADING - frozen_string_literal: true + <<-HEADING +frozen_string_literal: true - This file was generated with a custom heading! +This file was generated with a custom heading! HEADING end let(:subject) { described_class.new } let(:single_line_subject) do - described_class.new(heading: single_line_heading) + described_class.new(:heading => single_line_heading) end let(:multi_line_single_quotes_subject) do - described_class.new(heading: multi_line_heading, single_quotes: true) + described_class.new(:heading => multi_line_heading, :single_quotes => true) end describe ".heading" do it "returns nil if no heading is set" do subject - expect(described_class.heading(appraisal)).to eq(nil) + expect(described_class.heading(appraisal)).to be_nil end it "returns the heading if set" do @@ -36,19 +36,19 @@ it "returns the heading without an trailing newline" do multi_line_single_quotes_subject expect(described_class.heading(appraisal)).to eq(multi_line_heading.chomp) - expect(described_class.heading(appraisal)).to_not end_with("\n") + expect(described_class.heading(appraisal)).not_to end_with("\n") end end describe ".single_quotes" do it "returns false if not set" do subject - expect(described_class.single_quotes).to eq(false) + expect(described_class.single_quotes).to be(false) end it "returns true if set" do multi_line_single_quotes_subject - expect(described_class.single_quotes).to eq(true) + expect(described_class.single_quotes).to be(true) end end @@ -60,6 +60,7 @@ let(:lockfile_relative_path) { "gemfiles/#{lockfile}" } let(:gemfile_full_path) { "/path/to/project/#{gemfile_relative_path}" } let(:lockfile_full_path) { "/path/to/project/#{lockfile_relative_path}" } + before do allow(appraisal).to receive(:gemfile_name).and_return(gemfile) allow(appraisal).to receive(:gemfile_path).and_return(gemfile_full_path) @@ -69,72 +70,72 @@ it "returns nil if no heading is set" do subject - expect(described_class.send(:customize, nil, appraisal)).to eq(nil) + expect(described_class.send(:customize, nil, appraisal)).to be_nil end it "returns the heading unchanged" do single_line_subject expect(described_class.send( - :customize, - single_line_heading, - appraisal - )).to eq(single_line_heading) + :customize, + single_line_heading, + appraisal, + )).to eq(single_line_heading) end it "returns the heading with the appraisal name" do expect(described_class.send( - :customize, - "Appraisal: %{appraisal}", # rubocop:disable Style/FormatStringToken - appraisal - )).to eq("Appraisal: #{appraisal_name}") + :customize, + "Appraisal: %{appraisal}", # rubocop:disable Style/FormatStringToken + appraisal, + )).to eq("Appraisal: #{appraisal_name}") end it "returns the heading with the gemfile name" do expect(described_class.send( - :customize, - "Gemfile: %{gemfile}", # rubocop:disable Style/FormatStringToken - appraisal - )).to eq("Gemfile: #{gemfile}") + :customize, + "Gemfile: %{gemfile}", # rubocop:disable Style/FormatStringToken + appraisal, + )).to eq("Gemfile: #{gemfile}") end it "returns the heading with the gemfile path" do expect(described_class.send( - :customize, - "Gemfile: %{gemfile_path}", # rubocop:disable Style/FormatStringToken - appraisal - )).to eq("Gemfile: #{gemfile_full_path}") + :customize, + "Gemfile: %{gemfile_path}", # rubocop:disable Style/FormatStringToken + appraisal, + )).to eq("Gemfile: #{gemfile_full_path}") end it "returns the heading with the lockfile name" do expect(described_class.send( - :customize, - "Lockfile: %{lockfile}", # rubocop:disable Style/FormatStringToken - appraisal - )).to eq("Lockfile: #{lockfile}") + :customize, + "Lockfile: %{lockfile}", # rubocop:disable Style/FormatStringToken + appraisal, + )).to eq("Lockfile: #{lockfile}") end it "returns the heading with the lockfile path" do expect(described_class.send( - :customize, - "Lockfile: %{lockfile_path}", # rubocop:disable Style/FormatStringToken - appraisal - )).to eq("Lockfile: #{lockfile_full_path}") + :customize, + "Lockfile: %{lockfile_path}", # rubocop:disable Style/FormatStringToken + appraisal, + )).to eq("Lockfile: #{lockfile_full_path}") end it "returns the heading with the relative gemfile path" do expect(described_class.send( - :customize, - "Gemfile: %{relative_gemfile_path}", # rubocop:disable Style/FormatStringToken - appraisal - )).to eq("Gemfile: #{gemfile_relative_path}") + :customize, + "Gemfile: %{relative_gemfile_path}", # rubocop:disable Style/FormatStringToken + appraisal, + )).to eq("Gemfile: #{gemfile_relative_path}") end it "returns the heading with the relative lockfile path" do expect(described_class.send( - :customize, - "Gemfile: %{relative_lockfile_path}", # rubocop:disable Style/FormatStringToken - appraisal - )).to eq("Gemfile: #{lockfile_relative_path}") + :customize, + "Gemfile: %{relative_lockfile_path}", # rubocop:disable Style/FormatStringToken + appraisal, + )).to eq("Gemfile: #{lockfile_relative_path}") end end end diff --git a/spec/appraisal/dependency_list_spec.rb b/spec/appraisal/dependency_list_spec.rb index 8b322984..7aa0c4a2 100644 --- a/spec/appraisal/dependency_list_spec.rb +++ b/spec/appraisal/dependency_list_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Appraisal::DependencyList do describe "#add" do - let(:dependency_list) { Appraisal::DependencyList.new } + let(:dependency_list) { described_class.new } it "adds dependency to the list" do dependency_list.add("rails", ["4.1.4"]) @@ -32,7 +32,7 @@ end describe "#remove" do - let(:dependency_list) { Appraisal::DependencyList.new } + let(:dependency_list) { described_class.new } before do dependency_list.add("rails", ["4.1.4"]) diff --git a/spec/appraisal/gemfile_spec.rb b/spec/appraisal/gemfile_spec.rb index 666c07ba..2e88f728 100644 --- a/spec/appraisal/gemfile_spec.rb +++ b/spec/appraisal/gemfile_spec.rb @@ -8,26 +8,26 @@ include StreamHelpers it "supports gemfiles without sources" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new expect(gemfile.to_s.strip).to eq "" end it "supports multiple sources" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.source "one" gemfile.source "two" expect(gemfile.to_s.strip).to eq %(source "one"\nsource "two") end it "ignores duplicate sources" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.source "one" gemfile.source "one" expect(gemfile.to_s.strip).to eq %(source "one") end it "preserves dependency order" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.gem "one" gemfile.gem "two" gemfile.gem "three" @@ -35,13 +35,13 @@ end it "supports symbol sources" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.source :one expect(gemfile.to_s.strip).to eq %(source :one) end it "supports group syntax" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.group :development, :test do gem "one" @@ -55,7 +55,7 @@ end it "supports nested DSL within group syntax" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.group :development, :test do platforms :jruby do @@ -87,7 +87,7 @@ end it "supports platform syntax" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.platform :jruby do gem "one" @@ -101,7 +101,7 @@ end it "supports nested DSL within platform syntax" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.platform :jruby do group :development, :test do @@ -133,7 +133,7 @@ end it "supports git syntax" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.git "git://example.com/repo.git" do gem "one" @@ -147,7 +147,7 @@ end it "supports nested DSL within git syntax" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.git "git://example.com/repo.git" do group :development, :test do @@ -179,7 +179,7 @@ end it "supports path syntax" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.path "../path" do gem "one" @@ -193,7 +193,7 @@ end it "supports nested DSL within path syntax" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.path "../path" do group :development, :test do @@ -227,14 +227,14 @@ context "excess new line" do context "no contents" do it "shows empty string" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new expect(gemfile.to_s).to eq "" end end context "full contents" do it "does not show newline at end" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.source "source" gemfile.gem "gem" gemfile.gemspec @@ -244,7 +244,7 @@ context "no gemspec" do it "does not show newline at end" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.source "source" gemfile.gem "gem" expect(gemfile.to_s).to match(/[^\n]\z/m) @@ -253,64 +253,65 @@ end context "relative path handling" do - before { stub_const("RUBY_VERSION", "2.3.0") } + before { stub_const("RUBY_VERSION", "1.8.7") } context "in :path option" do it "handles dot path" do - gemfile = Appraisal::Gemfile.new - gemfile.gem "bacon", path: "." + gemfile = described_class.new + gemfile.gem "bacon", :path => "." - expect(gemfile.to_s).to eq %(gem "bacon", path: "../") + expect(gemfile.to_s).to eq %(gem "bacon", :path => "../") end it "handles relative path" do - gemfile = Appraisal::Gemfile.new - gemfile.gem "bacon", path: "../bacon" + gemfile = described_class.new + gemfile.gem "bacon", :path => "../bacon" - expect(gemfile.to_s).to eq %(gem "bacon", path: "../../bacon") + expect(gemfile.to_s).to eq %(gem "bacon", :path => "../../bacon") end it "handles absolute path" do - gemfile = Appraisal::Gemfile.new - gemfile.gem "bacon", path: "/tmp" + gemfile = described_class.new + gemfile.gem "bacon", :path => "/tmp" - expect(gemfile.to_s).to eq %(gem "bacon", path: "/tmp") + expect(gemfile.to_s).to eq %(gem "bacon", :path => "/tmp") end end context "in :git option" do it "handles dot git path" do - gemfile = Appraisal::Gemfile.new - gemfile.gem "bacon", git: "." + gemfile = described_class.new + gemfile.gem "bacon", :git => "." - expect(gemfile.to_s).to eq %(gem "bacon", git: "../") + expect(gemfile.to_s).to eq %(gem "bacon", :git => "../") end it "handles relative git path" do - gemfile = Appraisal::Gemfile.new - gemfile.gem "bacon", git: "../bacon" + gemfile = described_class.new + gemfile.gem "bacon", :git => "../bacon" - expect(gemfile.to_s).to eq %(gem "bacon", git: "../../bacon") + expect(gemfile.to_s).to eq %(gem "bacon", :git => "../../bacon") end it "handles absolute git path" do - gemfile = Appraisal::Gemfile.new - gemfile.gem "bacon", git: "/tmp" + gemfile = described_class.new + gemfile.gem "bacon", :git => "/tmp" - expect(gemfile.to_s).to eq %(gem "bacon", git: "/tmp") + expect(gemfile.to_s).to eq %(gem "bacon", :git => "/tmp") end it "handles git uri" do - gemfile = Appraisal::Gemfile.new - gemfile.gem "bacon", git: "git@github.com:bacon/bacon.git" + gemfile = described_class.new + gemfile.gem "bacon", :git => "git@github.com:bacon/bacon.git" - expect(gemfile.to_s).to eq %(gem "bacon", git: "git@github.com:bacon/bacon.git") + expect(gemfile.to_s) + .to eq %(gem "bacon", :git => "git@github.com:bacon/bacon.git") end end context "in path block" do it "handles dot path" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.path "." do gem "bacon" @@ -324,7 +325,7 @@ end it "handles relative path" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.path "../bacon" do gem "bacon" @@ -338,7 +339,7 @@ end it "handles absolute path" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.path "/tmp" do gem "bacon" @@ -354,7 +355,7 @@ context "in git block" do it "handles dot git path" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.git "." do gem "bacon" @@ -368,7 +369,7 @@ end it "handles relative git path" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.git "../bacon" do gem "bacon" @@ -382,7 +383,7 @@ end it "handles absolute git path" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.git "/tmp" do gem "bacon" @@ -396,7 +397,7 @@ end it "handles git uri" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.git "git@github.com:bacon/bacon.git" do gem "bacon" @@ -412,28 +413,28 @@ context "in gemspec directive" do it "handles gemspec path" do - gemfile = Appraisal::Gemfile.new - gemfile.gemspec path: "." + gemfile = described_class.new + gemfile.gemspec :path => "." - expect(gemfile.to_s).to eq %(gemspec path: "../") + expect(gemfile.to_s).to eq %(gemspec :path => "../") end end end context "git_source support" do - before { stub_const("RUBY_VERSION", "2.3.0") } + before { stub_const("RUBY_VERSION", "1.8.7") } it "stores git_source declaration and apply it as git option" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new gemfile.git_source(:custom_source) { |repo| "path/#{repo}" } - gemfile.gem "bacon", custom_source: "bacon_pancake" + gemfile.gem "bacon", :custom_source => "bacon_pancake" - expect(gemfile.to_s).to eq %(gem "bacon", git: "../path/bacon_pancake") + expect(gemfile.to_s).to eq %(gem "bacon", :git => "../path/bacon_pancake") end end it "preserves the Gemfile's __FILE__" do - gemfile = Appraisal::Gemfile.new + gemfile = described_class.new Tempfile.open do |tmpfile| tmpfile.write "__FILE__" tmpfile.rewind diff --git a/spec/appraisal/utils_spec.rb b/spec/appraisal/utils_spec.rb index 04dfe910..743f8683 100644 --- a/spec/appraisal/utils_spec.rb +++ b/spec/appraisal/utils_spec.rb @@ -5,61 +5,64 @@ RSpec.describe Appraisal::Utils do describe ".format_string" do - it "prints out a nice looking hash without brackets with new syntax" do - hash = { foo: "bar" } - expect(Appraisal::Utils.format_string(hash)).to eq('foo: "bar"') + it "prints out a nice looking hash without brackets with old syntax" do + hash = {:foo => "bar"} + expect(described_class.format_string(hash)).to eq(':foo => "bar"') - hash = { "baz" => { ball: "boo" } } - expect(Appraisal::Utils.format_string(hash)).to eq('"baz" => { ball: "boo" }') + hash = {"baz" => {:ball => "boo"}} + expect(described_class.format_string(hash)) + .to eq('"baz" => { :ball => "boo" }') end end describe ".format_arguments" do - before { stub_const("RUBY_VERSION", "2.3.0") } + before { stub_const("RUBY_VERSION", "1.8.7") } it "prints out arguments without enclosing square brackets" do - arguments = [:foo, { bar: { baz: "ball" } }] + arguments = [:foo, {:bar => {:baz => "ball"}}] - expect(Appraisal::Utils.format_arguments(arguments)).to eq(':foo, bar: { baz: "ball" }') + expect(described_class.format_arguments(arguments)).to eq( + ':foo, :bar => { :baz => "ball" }', + ) end it "returns nil if arguments is empty" do arguments = [] - expect(Appraisal::Utils.format_arguments(arguments)).to eq(nil) + expect(described_class.format_arguments(arguments)).to be_nil end end describe ".prefix_path" do it "prepends two dots in front of relative path" do - expect(Appraisal::Utils.prefix_path("test")).to eq "../test" + expect(described_class.prefix_path("test")).to eq "../test" end it "replaces single dot with two dots" do - expect(Appraisal::Utils.prefix_path(".")).to eq "../" + expect(described_class.prefix_path(".")).to eq "../" end it "ignores absolute path" do - expect(Appraisal::Utils.prefix_path("/tmp")).to eq "/tmp" + expect(described_class.prefix_path("/tmp")).to eq "/tmp" end it "strips out './' from path" do - expect(Appraisal::Utils.prefix_path("./tmp/./appraisal././")).to eq "../tmp/appraisal./" + expect(described_class.prefix_path("./tmp/./appraisal././")).to eq "../tmp/appraisal./" end it "does not prefix Git uri" do - expect(Appraisal::Utils.prefix_path("git@github.com:bacon/bacon.git")).to eq "git@github.com:bacon/bacon.git" - expect(Appraisal::Utils.prefix_path("git://github.com/bacon/bacon.git")).to eq "git://github.com/bacon/bacon.git" - expect(Appraisal::Utils.prefix_path("https://github.com/bacon/bacon.git")).to eq("https://github.com/bacon/bacon.git") + expect(described_class.prefix_path("git@github.com:bacon/bacon.git")).to eq "git@github.com:bacon/bacon.git" + expect(described_class.prefix_path("git://github.com/bacon/bacon.git")).to eq "git://github.com/bacon/bacon.git" + expect(described_class.prefix_path("https://github.com/bacon/bacon.git")).to eq("https://github.com/bacon/bacon.git") end end describe ".bundler_version" do it "returns the bundler version" do - bundler = double("Bundler", name: "bundler", version: "a.b.c") + bundler = double("Bundler", :name => "bundler", :version => "a.b.c") allow(Gem::Specification).to receive(:detect).and_return(bundler) - version = Appraisal::Utils.bundler_version + version = described_class.bundler_version expect(version).to eq "a.b.c" expect(Gem::Specification).to have_received(:detect) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 20b036de..24416362 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require "rubygems" -require "bundler/setup" +require "byebug" if ENV["CI"].nil? && ENV["DEBUG"] == "true" require "./spec/support/acceptance_test_helpers" require "./spec/support/stream_helpers" @@ -13,11 +13,11 @@ RSpec.configure do |config| config.raise_errors_for_deprecations! - config.define_derived_metadata(file_path: %r{spec\/acceptance\/}) do |metadata| + config.define_derived_metadata(:file_path => %r{spec/acceptance/}) do |metadata| metadata[:type] = :acceptance end - config.include AcceptanceTestHelpers, type: :acceptance + config.include AcceptanceTestHelpers, :type => :acceptance # disable monkey patching # see: https://relishapp.com/rspec/rspec-core/v/3-8/docs/configuration/zero-monkey-patching-mode diff --git a/spec/support/acceptance_test_helpers.rb b/spec/support/acceptance_test_helpers.rb index 52e0c60a..038f7b3f 100644 --- a/spec/support/acceptance_test_helpers.rb +++ b/spec/support/acceptance_test_helpers.rb @@ -22,7 +22,7 @@ module AcceptanceTestHelpers included do metadata[:type] = :acceptance - before parallel: true do + before :parallel => true do unless Appraisal::Utils.support_parallel_installation? pending "This Bundler version does not support --jobs flag." end @@ -58,7 +58,7 @@ def unset_bundler_environment_variables end def add_binstub_path - ENV["PATH"] = "bin:#{ENV['PATH']}" + ENV["PATH"] = "bin:#{ENV["PATH"]}" end def restore_environment_variables @@ -94,7 +94,7 @@ def build_gemspec def content_of(path) file(path).read.tap do |content| - content.gsub!(/(\S+): /, ":\\1 => ") + content.gsub!(/(\S+): /, ':\\1 => ') end end @@ -130,15 +130,15 @@ def build_default_dummy_gems def ensure_bundler_is_available run "bundle -v 2>&1", false - if $?.exitstatus != 0 - puts <<-WARNING.squish.strip_heredoc + return unless $?.exitstatus != 0 + + puts <<-WARNING.squish.strip_heredoc Reinstall Bundler to #{TMP_GEM_ROOT} as `BUNDLE_DISABLE_SHARED_GEMS` is enabled. - WARNING - version = Utils.bundler_version + WARNING + version = Utils.bundler_version - run "gem install bundler --version #{version} --install-dir '#{TMP_GEM_ROOT}'" - end + run "gem install bundler --version #{version} --install-dir '#{TMP_GEM_ROOT}'" end def build_default_gemfile @@ -146,9 +146,20 @@ def build_default_gemfile source 'https://rubygems.org' gem 'appraisal', :path => '#{PROJECT_ROOT}' + + if RUBY_VERSION < "1.9" + #{File.read(File.join(PROJECT_ROOT, "Gemfile-1.8"))} + elsif RUBY_VERSION < "2.2" + #{File.read(File.join(PROJECT_ROOT, "Gemfile-2.1"))} + end GEMFILE run "bundle install --local" + # Support for binstubs --all was added to bundler's 1-17-stable branch + # and released with bundler v1.17.0.pre.2 (2018-10-13) + # See: + # - https://github.com/rubygems/bundler/pull/6450 + # - https://github.com/rubygems/bundler/commit/9d59fa41ef43aaccc6cf867a69a49648510c4df7#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4edR10 run "bundle binstubs --all" end @@ -159,17 +170,15 @@ def in_test_directory(&block) def run(command, raise_on_error = true) in_test_directory do - `#{command}`.tap do |output| + %x(#{command}).tap do |output| exitstatus = $?.exitstatus - if ENV["VERBOSE"] - puts output - end + puts output if ENV["VERBOSE"] if raise_on_error && exitstatus != 0 - raise RuntimeError, <<-ERROR_MESSAGE.strip_heredoc + raise <<-ERROR_MESSAGE.strip_heredoc.to_s Command #{command.inspect} exited with status #{exitstatus}. Output: - #{output.gsub(/^/, ' ')} + #{output.gsub(/^/, " ")} ERROR_MESSAGE end end diff --git a/spec/support/dependency_helpers.rb b/spec/support/dependency_helpers.rb index 54752d20..c8d21793 100644 --- a/spec/support/dependency_helpers.rb +++ b/spec/support/dependency_helpers.rb @@ -4,15 +4,16 @@ module DependencyHelpers def build_gem(gem_name, version = "1.0.0") ENV["GEM_HOME"] = TMP_GEM_ROOT - unless File.exist? "#{TMP_GEM_ROOT}/gems/#{gem_name}-#{version}" - FileUtils.mkdir_p "#{TMP_GEM_BUILD}/#{gem_name}/lib" + return if File.exist? "#{TMP_GEM_ROOT}/gems/#{gem_name}-#{version}" - FileUtils.cd "#{TMP_GEM_BUILD}/#{gem_name}" do - gemspec = "#{gem_name}.gemspec" - lib_file = "lib/#{gem_name}.rb" + FileUtils.mkdir_p "#{TMP_GEM_BUILD}/#{gem_name}/lib" - File.open gemspec, "w" do |file| - file.puts <<-GEMSPEC + FileUtils.cd "#{TMP_GEM_BUILD}/#{gem_name}" do + gemspec = "#{gem_name}.gemspec" + lib_file = "lib/#{gem_name}.rb" + + File.open gemspec, "w" do |file| + file.puts <<-GEMSPEC Gem::Specification.new do |s| s.name = #{gem_name.inspect} s.version = #{version.inspect} @@ -23,23 +24,22 @@ def build_gem(gem_name, version = "1.0.0") s.homepage = 'http://github.com/thoughtbot/#{gem_name}' s.required_ruby_version = '>= 2.3.0' end - GEMSPEC - end + GEMSPEC + end - File.open lib_file, "w" do |file| - file.puts "$#{gem_name}_version = '#{version}'" - end + File.open lib_file, "w" do |file| + file.puts "$#{gem_name}_version = '#{version}'" + end - redirect = ENV["VERBOSE"] ? "" : "2>&1" + redirect = ENV["VERBOSE"] ? "" : "2>&1" - puts "building gem: #{gem_name} #{version}" if ENV["VERBOSE"] - `gem build #{gemspec} #{redirect}` + puts "building gem: #{gem_name} #{version}" if ENV["VERBOSE"] + %x(gem build #{gemspec} #{redirect}) - puts "installing gem: #{gem_name} #{version}" if ENV["VERBOSE"] - `gem install -lN #{gem_name}-#{version}.gem -v #{version} #{redirect}` + puts "installing gem: #{gem_name} #{version}" if ENV["VERBOSE"] + %x(gem install -lN #{gem_name}-#{version}.gem -v #{version} #{redirect}) - puts "" if ENV["VERBOSE"] - end + puts "" if ENV["VERBOSE"] end end @@ -52,11 +52,12 @@ def build_git_gem(gem_name, version = "1.0.0") build_gem gem_name, version Dir.chdir "#{TMP_GEM_BUILD}/#{gem_name}" do - `git init . --initial-branch=master` - `git config user.email "appraisal@thoughtbot.com"` - `git config user.name "Appraisal"` - `git add .` - `git commit --all --no-verify --message "initial commit"` + %x(git init . --initial-branch=master) + %x(git config user.email "appraisal@thoughtbot.com") + %x(git config user.name "Appraisal") + %x(git config commit.gpgsign false) + %x(git add .) + %x(git commit --all --no-verify --message "initial commit") end # Cleanup Bundler cache path manually for now diff --git a/spec/support/stream_helpers.rb b/spec/support/stream_helpers.rb index ca0eb436..97c0240d 100644 --- a/spec/support/stream_helpers.rb +++ b/spec/support/stream_helpers.rb @@ -13,7 +13,7 @@ def capture(stream) yield stream_io.rewind - return captured_stream.read + captured_stream.read ensure captured_stream.close captured_stream.unlink From 14f36cd74767904146ab7f902101faff64451e70 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Fri, 21 Feb 2025 04:39:18 +0700 Subject: [PATCH 02/60] =?UTF-8?q?=F0=9F=92=9A=20Fix=20bundler=20versions?= =?UTF-8?q?=20per=20Ruby=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - https://dev.to/galtzo/matrix-ruby-gem-bundler-etc-4kk7 --- .github/workflows/main.yml | 1 + Gemfile | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7e5742e3..1d390315 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,6 +38,7 @@ jobs: - name: Update bundler env: RUBY_VERSION: ${{ matrix.ruby }} + # See: https://dev.to/galtzo/matrix-ruby-gem-bundler-etc-4kk7 run: | case ${RUBY_VERSION} in 1.8|1.9|2.0|2.1|2.2) diff --git a/Gemfile b/Gemfile index e73905ca..1f4f2868 100644 --- a/Gemfile +++ b/Gemfile @@ -27,5 +27,15 @@ elsif ruby_version < Gem::Version.new("2.7") else # Ruby >= 2.7 we can run style / lint checks via rubocop-gradual with rubocop-lts rules for Ruby 1.8+. # This means we can develop on modern Ruby but remain compatible with ancient Ruby. - eval_gemfile "gemfiles/modular/style.gemfile" + # TODO: Replace individual style gems below with modular gemfile, once eval_gemfile support is added to appraisal. + # eval_gemfile "gemfiles/modular/style.gemfile" + # We run rubocop on the latest version of Ruby, + # but in support of the oldest supported version of Ruby + gem "rubocop-lts", "~> 0.1", ">= 0.1.1" # Style and Linting support for Ruby >= 1.8 + gem "rubocop-packaging", "~> 0.5", ">= 0.5.2" + gem "rubocop-rspec", "~> 3.2" + gem "standard", ">= 1.35.1", "!= 1.41.1", "!= 1.42.0" + + # Std Lib extractions + gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 end From 79a6de1a0829d409a9d53ece16a5f8dc82b1a4cc Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Fri, 21 Feb 2025 05:34:03 +0700 Subject: [PATCH 03/60] =?UTF-8?q?=F0=9F=92=9A=20Fix=20ruby=20declaration?= =?UTF-8?q?=20in=20Gemfile=20when=20on=20ruby-head?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Support debug for debugging with Ruby >= 2.7 - Support byebug for debugging with Ruby < 2.7 --- .tool-versions | 2 +- Gemfile | 13 ++++++++++--- ...ppraisals_file_bundler_dsl_compatibility_spec.rb | 4 ++-- spec/acceptance/gemfile_dsl_compatibility_spec.rb | 6 +++--- spec/spec_helper.rb | 11 ++++++++++- spec/support/acceptance_test_helpers.rb | 9 +++++++++ 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/.tool-versions b/.tool-versions index ae5ecdb2..0964b2a6 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 3.4.2 +ruby 3.5-dev diff --git a/Gemfile b/Gemfile index 1f4f2868..d90a1616 100644 --- a/Gemfile +++ b/Gemfile @@ -2,9 +2,18 @@ source "https://rubygems.org" gemspec +# For Ruby version specific dependencies +ruby_version = Gem::Version.new(RUBY_VERSION) + platform :mri do # Debugging - gem "byebug", ">= 11" + if ruby_version < Gem::Version.new("2.7") + # Use byebug in code + gem "byebug", ">= 11" + else + # Use binding.break, binding.b, or debugger in code + gem "debug", ">= 1.0.0" + end # Dev Console - Binding.pry - Irb replacement gem "pry", "~> 0.14" # ruby >= 2.0 @@ -13,8 +22,6 @@ end # This here to make sure appraisal works with Rails 3.0.0. gem "thor", "~> 0.14.0" -# Ruby version specific dependencies -ruby_version = Gem::Version.new(RUBY_VERSION) if ruby_version < Gem::Version.new("1.9") eval File.read("Gemfile-1.8") elsif ruby_version < Gem::Version.new("2.1") diff --git a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb index b5a46e6b..885eedb8 100644 --- a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb +++ b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb @@ -21,7 +21,7 @@ build_gemfile <<-GEMFILE source 'https://rubygems.org' git_source(:custom_git_source) { |repo| "../build/\#{repo}" } - ruby RUBY_VERSION + ruby "#{RUBY_VERSION}#{ruby_dev_append}" gem 'bagel' gem "croissant", :custom_git_source => "croissant" @@ -166,7 +166,7 @@ build_gemfile <<-GEMFILE source 'https://rubygems.org' - ruby RUBY_VERSION + ruby "#{RUBY_VERSION}#{ruby_dev_append}" gem 'appraisal', :path => #{PROJECT_ROOT.inspect} GEMFILE diff --git a/spec/acceptance/gemfile_dsl_compatibility_spec.rb b/spec/acceptance/gemfile_dsl_compatibility_spec.rb index 2a9dcac3..d01751e3 100644 --- a/spec/acceptance/gemfile_dsl_compatibility_spec.rb +++ b/spec/acceptance/gemfile_dsl_compatibility_spec.rb @@ -10,7 +10,7 @@ build_gemfile <<-GEMFILE source "https://rubygems.org" - ruby RUBY_VERSION + ruby "#{RUBY_VERSION}#{ruby_dev_append}" git "../build/egg" do gem "egg" @@ -52,7 +52,7 @@ source "https://rubygems.org" - ruby "#{RUBY_VERSION}" + ruby "#{RUBY_VERSION}#{ruby_dev_append}" git "../../build/egg" do gem "egg" @@ -82,7 +82,7 @@ source "https://rubygems.org" - ruby "#{RUBY_VERSION}" + ruby "#{RUBY_VERSION}#{ruby_dev_append}" git "../../build/egg" do gem "egg" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 24416362..62de10b9 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,16 @@ # frozen_string_literal: true require "rubygems" -require "byebug" if ENV["CI"].nil? && ENV["DEBUG"] == "true" +if ENV["CI"].nil? && ENV["DEBUG"] == "true" + ruby_version = Gem::Version.new(RUBY_VERSION) + if ruby_version < Gem::Version.new("2.7") + # Use byebug in code + require "byebug" + else + # Use binding.break, binding.b, or debugger in code + require "debug" + end +end require "./spec/support/acceptance_test_helpers" require "./spec/support/stream_helpers" diff --git a/spec/support/acceptance_test_helpers.rb b/spec/support/acceptance_test_helpers.rb index 038f7b3f..d577580d 100644 --- a/spec/support/acceptance_test_helpers.rb +++ b/spec/support/acceptance_test_helpers.rb @@ -43,6 +43,15 @@ module AcceptanceTestHelpers end end + # A head version of MRI ruby will require the -dev appended to the ruby string in the gemfile. + # Unfortunately, there is no ENV variable that has access to the "dev" concept directly. + # Perhaps the best we can do is parse RUBY_DESCRIPTION? + # > RUBY_DESCRIPTION + # "ruby 3.5.0dev (2025-02-20T18:14:37Z master b2cf48f406) +PRISM [arm64-darwin24]" + def ruby_dev_append + RUBY_DESCRIPTION.include?("dev") ? "-dev" : "" + end + def save_environment_variables @original_environment_variables = {} From 2d022fcbd3f0404f07e570ca78d7e256eaddebcb Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Fri, 21 Feb 2025 05:37:13 +0700 Subject: [PATCH 04/60] =?UTF-8?q?=F0=9F=9A=A8=20Address=20code=20review=20?= =?UTF-8?q?from=20@n-rodriguez?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - https://github.com/thoughtbot/appraisal/pull/250#discussion_r1964410061 --- spec/acceptance/cli/update_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/acceptance/cli/update_spec.rb b/spec/acceptance/cli/update_spec.rb index 3819a81c..40d93be0 100644 --- a/spec/acceptance/cli/update_spec.rb +++ b/spec/acceptance/cli/update_spec.rb @@ -20,8 +20,8 @@ after do in_test_directory do - %x{gem uninstall dummy -v 1.0.1} - %x{gem uninstall dummy2 -a} + %x(gem uninstall dummy -v 1.0.1) + %x(gem uninstall dummy2 -a) end end From df41df2bddb5214baa4467024f0c3475114e86a5 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Fri, 21 Feb 2025 05:50:25 +0700 Subject: [PATCH 05/60] =?UTF-8?q?=F0=9F=91=B7=20Add=20Rubies=202.7,=202.6,?= =?UTF-8?q?=202.5,=202.4,=202.3,=202.2,=202.1,=202.0,=201.9,=201.8=20to=20?= =?UTF-8?q?build=20matrix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - all current jruby and truffleruby are compatible with Ruby 3.1 at minimum, thus are supported by latest bundler --- .github/workflows/main.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1d390315..42377a64 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,6 +21,16 @@ jobs: - '3.2' - '3.1' - '3.0' + - '2.7' + - '2.6' + - '2.5' + - '2.4' + - '2.3' + - '2.2' + - '2.1' + - '2.0' + - '1.9' + - '1.8' - 'head' - jruby - jruby-head @@ -57,10 +67,6 @@ jobs: gem install bundler -v 2.5.23 ;; - truffleruby|truffleruby-head) - gem install bundler -v 2.5.23 - ;; - *) gem update --system ;; From 1a5b85d9caa1a537f4e6412f0636ec784231ca0f Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Fri, 21 Feb 2025 06:59:12 +0700 Subject: [PATCH 06/60] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20.rspec=20to=20?= =?UTF-8?q?dry=20spec=20file=20headers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use strip_heredoc uniformly in acceptance tests --- .rspec | 3 ++ .tool-versions | 2 +- lib/appraisal/command.rb | 10 +++---- lib/appraisal/group.rb | 8 ++--- ...als_file_bundler_dsl_compatibility_spec.rb | 10 +++---- .../bundle_with_custom_path_spec.rb | 8 ++--- spec/acceptance/bundle_without_spec.rb | 6 ++-- spec/acceptance/cli/clean_spec.rb | 4 +-- spec/acceptance/cli/generate_spec.rb | 6 ++-- spec/acceptance/cli/help_spec.rb | 4 +-- spec/acceptance/cli/install_spec.rb | 14 ++++----- spec/acceptance/cli/list_spec.rb | 4 +-- spec/acceptance/cli/run_spec.rb | 4 +-- spec/acceptance/cli/update_spec.rb | 4 +-- spec/acceptance/cli/version_spec.rb | 2 -- spec/acceptance/cli/with_no_arguments_spec.rb | 4 +-- .../gemfile_dsl_compatibility_spec.rb | 14 ++++----- spec/acceptance/gemspec_spec.rb | 12 ++++---- spec/appraisal/appraisal_spec.rb | 12 ++++---- spec/appraisal/customize_spec.rb | 6 ++-- spec/appraisal/dependency_list_spec.rb | 2 +- spec/appraisal/gemfile_spec.rb | 30 +++++++++---------- spec/spec_helper.rb | 13 ++++++-- spec/support/acceptance_test_helpers.rb | 23 ++++++-------- spec/support/dependency_helpers.rb | 2 +- spec/support/stream_helpers.rb | 1 + 26 files changed, 94 insertions(+), 114 deletions(-) create mode 100644 .rspec diff --git a/.rspec b/.rspec new file mode 100644 index 00000000..bd5e0288 --- /dev/null +++ b/.rspec @@ -0,0 +1,3 @@ +--format progress +--color +--require spec_helper diff --git a/.tool-versions b/.tool-versions index 0964b2a6..59511e1d 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 3.5-dev +ruby 2.7.8 diff --git a/lib/appraisal/command.rb b/lib/appraisal/command.rb index 76ac69f2..dd29ea44 100644 --- a/lib/appraisal/command.rb +++ b/lib/appraisal/command.rb @@ -41,11 +41,11 @@ def ensure_bundler_is_available return if system("gem install bundler --version #{version}") puts - puts <<-ERROR.strip.gsub(/\s+/, " ") - Bundler installation failed. - Please try running: - `GEM_HOME="#{ENV["GEM_HOME"]}" gem install bundler --version #{version}` - manually. + puts <<-ERROR.strip_heredoc + Bundler installation failed. + Please try running: + `GEM_HOME="#{ENV["GEM_HOME"]}" gem install bundler --version #{version}` + manually. ERROR exit(1) end diff --git a/lib/appraisal/group.rb b/lib/appraisal/group.rb index 50351a88..f1f82314 100644 --- a/lib/appraisal/group.rb +++ b/lib/appraisal/group.rb @@ -22,10 +22,10 @@ def for_dup private def formatted_output(output_dependencies) - <<-OUTPUT.strip -group #{Utils.format_arguments(@group_names)} do -#{output_dependencies} -end + <<-OUTPUT.strip_heredoc + group #{Utils.format_arguments(@group_names)} do + #{output_dependencies} + end OUTPUT end end diff --git a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb index 885eedb8..41e669ee 100644 --- a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb +++ b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "Appraisals file Bundler DSL compatibility" do it "supports all Bundler DSL in Appraisals file" do build_gems %w[ @@ -18,7 +16,7 @@ ] build_git_gems %w[egg croissant pain_au_chocolat omelette] - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source 'https://rubygems.org' git_source(:custom_git_source) { |repo| "../build/\#{repo}" } ruby "#{RUBY_VERSION}#{ruby_dev_append}" @@ -59,7 +57,7 @@ gem 'appraisal', :path => #{PROJECT_ROOT.inspect} GEMFILE - build_appraisal_file <<-APPRAISALS + build_appraisal_file <<-APPRAISALS.strip_heredoc appraise 'breakfast' do source 'http://some-other-source.com' ruby "1.8.7" @@ -163,7 +161,7 @@ end it 'supports ruby file: ".ruby-version" DSL' do - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source 'https://rubygems.org' ruby "#{RUBY_VERSION}#{ruby_dev_append}" @@ -171,7 +169,7 @@ gem 'appraisal', :path => #{PROJECT_ROOT.inspect} GEMFILE - build_appraisal_file <<-APPRAISALS + build_appraisal_file <<-APPRAISALS.strip_heredoc appraise 'ruby-version' do ruby({:file => ".ruby-version"}) end diff --git a/spec/acceptance/bundle_with_custom_path_spec.rb b/spec/acceptance/bundle_with_custom_path_spec.rb index cdb92c0a..bb6fca1b 100644 --- a/spec/acceptance/bundle_with_custom_path_spec.rb +++ b/spec/acceptance/bundle_with_custom_path_spec.rb @@ -1,14 +1,12 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "Bundle with custom path" do let(:gem_name) { "rack" } let(:path) { "vendor/bundle" } shared_examples "gemfile dependencies are satisfied" do it "installs gems in the --path directory" do - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source "https://rubygems.org" gem 'appraisal', :path => #{PROJECT_ROOT.inspect} @@ -20,7 +18,7 @@ end GEMFILE - build_appraisal_file <<-APPRAISALS + build_appraisal_file <<-APPRAISALS.strip_heredoc appraise "#{gem_name}" do gem '#{gem_name}' end @@ -49,7 +47,7 @@ context "when already installed in vendor/another" do before do - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source "https://rubygems.org" if RUBY_VERSION <= "1.9" diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index 9ee14737..8960e031 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -1,13 +1,11 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "Bundle without group" do it "config set --local without group is honored by Bundler" do pending "config set --local without group support seems broken, see: https://github.com/rubygems/rubygems/issues/8518" build_gems %w[pancake orange_juice waffle coffee sausage soda] - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source "https://rubygems.org" gem "pancake" @@ -20,7 +18,7 @@ gem "appraisal", :path => #{PROJECT_ROOT.inspect} GEMFILE - build_appraisal_file <<-APPRAISALS + build_appraisal_file <<-APPRAISALS.strip_heredoc appraise "breakfast" do gem "waffle" diff --git a/spec/acceptance/cli/clean_spec.rb b/spec/acceptance/cli/clean_spec.rb index 7eed158c..164dc3f4 100644 --- a/spec/acceptance/cli/clean_spec.rb +++ b/spec/acceptance/cli/clean_spec.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI", "appraisal clean" do it "remove all gemfiles from gemfiles directory" do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/generate_spec.rb b/spec/acceptance/cli/generate_spec.rb index 285fc215..0c7eb454 100644 --- a/spec/acceptance/cli/generate_spec.rb +++ b/spec/acceptance/cli/generate_spec.rb @@ -1,16 +1,14 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI", "appraisal generate" do it "generates the gemfiles" do - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source "https://rubygems.org" gem "appraisal", :path => "#{PROJECT_ROOT}" GEMFILE - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/help_spec.rb b/spec/acceptance/cli/help_spec.rb index da99f7a3..45bc1e03 100644 --- a/spec/acceptance/cli/help_spec.rb +++ b/spec/acceptance/cli/help_spec.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI", "appraisal help" do it "prints usage along with commands, and list of appraisals" do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/install_spec.rb b/spec/acceptance/cli/install_spec.rb index 1e93029f..f92405ce 100644 --- a/spec/acceptance/cli/install_spec.rb +++ b/spec/acceptance/cli/install_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI", "appraisal install" do it "raises error when there is no Appraisals file" do output = run "appraisal install 2>&1", false @@ -10,7 +8,7 @@ end it "installs the dependencies" do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -30,7 +28,7 @@ build_gemspec add_gemspec_to_gemfile - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -49,7 +47,7 @@ uri_dummy_path = "#{current_directory}/uri_dummy" FileUtils.symlink(File.absolute_path("tmp/build/uri_dummy"), uri_dummy_path) - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'uri_dummy', git: 'file://#{uri_dummy_path}' end @@ -62,7 +60,7 @@ context "with job size", :parallel do before do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -86,7 +84,7 @@ context "with full-index", :parallel do before do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -102,7 +100,7 @@ context "with path", :parallel do before do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/list_spec.rb b/spec/acceptance/cli/list_spec.rb index 917712ee..e2777e17 100644 --- a/spec/acceptance/cli/list_spec.rb +++ b/spec/acceptance/cli/list_spec.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI", "appraisal list" do it "prints list of appraisals" do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/run_spec.rb b/spec/acceptance/cli/run_spec.rb index 6bfcfd8c..d0fd1ab9 100644 --- a/spec/acceptance/cli/run_spec.rb +++ b/spec/acceptance/cli/run_spec.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI appraisal (with arguments)" do before do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/update_spec.rb b/spec/acceptance/cli/update_spec.rb index 40d93be0..be66063b 100644 --- a/spec/acceptance/cli/update_spec.rb +++ b/spec/acceptance/cli/update_spec.rb @@ -1,12 +1,10 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI", "appraisal update" do before do build_gem "dummy2", "1.0.0" - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise 'dummy' do gem 'dummy', '~> 1.0.0' gem 'dummy2', '~> 1.0.0' diff --git a/spec/acceptance/cli/version_spec.rb b/spec/acceptance/cli/version_spec.rb index e47a6548..ab313df9 100644 --- a/spec/acceptance/cli/version_spec.rb +++ b/spec/acceptance/cli/version_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI", "appraisal version" do context "with version subcommand" do it "prints out version string" do diff --git a/spec/acceptance/cli/with_no_arguments_spec.rb b/spec/acceptance/cli/with_no_arguments_spec.rb index 4a04e64a..962a9bb1 100644 --- a/spec/acceptance/cli/with_no_arguments_spec.rb +++ b/spec/acceptance/cli/with_no_arguments_spec.rb @@ -1,10 +1,8 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "CLI appraisal (with no arguments)" do it "runs install command" do - build_appraisal_file <<-APPRAISAL + build_appraisal_file <<-APPRAISAL.strip_heredoc appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/gemfile_dsl_compatibility_spec.rb b/spec/acceptance/gemfile_dsl_compatibility_spec.rb index d01751e3..c2987251 100644 --- a/spec/acceptance/gemfile_dsl_compatibility_spec.rb +++ b/spec/acceptance/gemfile_dsl_compatibility_spec.rb @@ -1,14 +1,12 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "Gemfile DSL compatibility" do it "supports all Bundler DSL in Gemfile" do build_gems %w[bacon orange_juice waffle] build_git_gem "egg" build_gemspec - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source "https://rubygems.org" ruby "#{RUBY_VERSION}#{ruby_dev_append}" @@ -33,7 +31,7 @@ gemspec GEMFILE - build_appraisal_file <<-APPRAISALS + build_appraisal_file <<-APPRAISALS.strip_heredoc appraise "japanese" do gem "rice" gem "miso_soup" @@ -112,14 +110,14 @@ build_gem "bacon", "1.1.0" build_gem "bacon", "1.2.0" - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source "https://rubygems.org" gem "appraisal", :path => #{PROJECT_ROOT.inspect} gem "bacon", "1.2.0" GEMFILE - build_appraisal_file <<-APPRAISALS + build_appraisal_file <<-APPRAISALS.strip_heredoc appraise "1.0.0" do gem "bacon", "1.0.0" end @@ -145,7 +143,7 @@ build_gem "bacon", "1.0.0" build_gemspec - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source "https://rubygems.org" gem "appraisal", :path => #{PROJECT_ROOT.inspect} @@ -155,7 +153,7 @@ end GEMFILE - build_appraisal_file <<-APPRAISALS + build_appraisal_file <<-APPRAISALS.strip_heredoc appraise "1.0.0" do gem "bacon", "1.0.0" end diff --git a/spec/acceptance/gemspec_spec.rb b/spec/acceptance/gemspec_spec.rb index fd93a11d..034ec1e4 100644 --- a/spec/acceptance/gemspec_spec.rb +++ b/spec/acceptance/gemspec_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "Gemspec" do before do build_appraisal_file @@ -11,7 +9,7 @@ it "supports gemspec syntax with default options" do build_gemspec - write_file "Gemfile", <<-GEMFILE + write_file "Gemfile", <<-GEMFILE.strip_heredoc source "https://rubygems.org" gem 'appraisal', :path => #{PROJECT_ROOT.inspect} @@ -29,7 +27,7 @@ it "supports gemspec syntax with path option" do build_gemspec "specdir" - write_file "Gemfile", <<-GEMFILE + write_file "Gemfile", <<-GEMFILE.strip_heredoc source "https://rubygems.org" gem 'appraisal', :path => #{PROJECT_ROOT.inspect} @@ -45,7 +43,7 @@ end def build_appraisal_file - appraisals = <<-APPRAISALS + appraisals = <<-APPRAISALS.strip_heredoc appraise 'stock' do gem 'rake' end @@ -54,7 +52,7 @@ def build_appraisal_file end def build_rakefile - write_file "Rakefile", <<-RAKEFILE + write_file "Rakefile", <<-RAKEFILE.strip_heredoc require 'rubygems' require 'bundler/setup' require 'appraisal' @@ -73,7 +71,7 @@ def build_gemspec(path = ".") nil end - write_file File.join(path, "gemspec_project.gemspec"), <<-GEMSPEC + write_file File.join(path, "gemspec_project.gemspec"), <<-GEMSPEC.strip_heredoc Gem::Specification.new do |s| s.name = 'gemspec_project' s.version = '0.1' diff --git a/spec/appraisal/appraisal_spec.rb b/spec/appraisal/appraisal_spec.rb index 031c871e..545ec8cf 100644 --- a/spec/appraisal/appraisal_spec.rb +++ b/spec/appraisal/appraisal_spec.rb @@ -45,9 +45,9 @@ end it "generates a gemfile with multiple lines of custom heading" do - heading = <<-HEADING -frozen_string_literal: true\n -This file was generated with a custom heading! + heading = <<-HEADING.strip_heredoc + frozen_string_literal: true\n + This file was generated with a custom heading! HEADING Appraisal::Customize.new(:heading => heading) output_file = Tempfile.new("gemfile") @@ -56,9 +56,9 @@ appraisal.write_gemfile - expected_output = <<-HEADING -# frozen_string_literal: true\n -# This file was generated with a custom heading! + expected_output = <<-HEADING.strip_heredoc + # frozen_string_literal: true\n + # This file was generated with a custom heading! HEADING expect(output_file.read).to start_with(expected_output) end diff --git a/spec/appraisal/customize_spec.rb b/spec/appraisal/customize_spec.rb index cc9e50f8..d3687a13 100644 --- a/spec/appraisal/customize_spec.rb +++ b/spec/appraisal/customize_spec.rb @@ -8,10 +8,10 @@ let(:appraisal) { Appraisal::Appraisal.new("test", "Gemfile") } let(:single_line_heading) { "This file was generated with a custom heading!" } let(:multi_line_heading) do - <<-HEADING -frozen_string_literal: true + <<-HEADING.strip_heredoc + frozen_string_literal: true -This file was generated with a custom heading! + This file was generated with a custom heading! HEADING end let(:subject) { described_class.new } diff --git a/spec/appraisal/dependency_list_spec.rb b/spec/appraisal/dependency_list_spec.rb index 7aa0c4a2..6d2b4def 100644 --- a/spec/appraisal/dependency_list_spec.rb +++ b/spec/appraisal/dependency_list_spec.rb @@ -17,7 +17,7 @@ dependency_list.add("rails", ["4.1.4"]) dependency_list.add("bundler", ["1.7.2"]) - expect(dependency_list.to_s).to eq <<-GEMS.strip_heredoc.strip + expect(dependency_list.to_s).to eq <<-GEMS.strip_heredoc gem "rails", "4.1.4" gem "bundler", "1.7.2" GEMS diff --git a/spec/appraisal/gemfile_spec.rb b/spec/appraisal/gemfile_spec.rb index 2e88f728..51b967ba 100644 --- a/spec/appraisal/gemfile_spec.rb +++ b/spec/appraisal/gemfile_spec.rb @@ -47,7 +47,7 @@ gem "one" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc group :development, :test do gem "one" end @@ -69,7 +69,7 @@ end end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc group :development, :test do git "git://example.com/repo.git" do gem "two" @@ -93,7 +93,7 @@ gem "one" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc platforms :jruby do gem "one" end @@ -115,7 +115,7 @@ end end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc platforms :jruby do git "git://example.com/repo.git" do gem "two" @@ -139,7 +139,7 @@ gem "one" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc git "git://example.com/repo.git" do gem "one" end @@ -161,7 +161,7 @@ end end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc git "git://example.com/repo.git" do path "../.." do gem "three" @@ -185,7 +185,7 @@ gem "one" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc path "../../path" do gem "one" end @@ -207,7 +207,7 @@ end end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc path "../../path" do git "git://example.com/repo.git" do gem "three" @@ -317,7 +317,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc path "../" do gem "bacon" end @@ -331,7 +331,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc path "../../bacon" do gem "bacon" end @@ -345,7 +345,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc path "/tmp" do gem "bacon" end @@ -361,7 +361,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc git "../" do gem "bacon" end @@ -375,7 +375,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc git "../../bacon" do gem "bacon" end @@ -389,7 +389,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc git "/tmp" do gem "bacon" end @@ -403,7 +403,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.strip + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc git "git@github.com:bacon/bacon.git" do gem "bacon" end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 62de10b9..d9313f5c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true require "rubygems" + if ENV["CI"].nil? && ENV["DEBUG"] == "true" + ENV["VERBOSE"] = "true" ruby_version = Gem::Version.new(RUBY_VERSION) if ruby_version < Gem::Version.new("2.7") # Use byebug in code @@ -11,8 +13,15 @@ require "debug" end end -require "./spec/support/acceptance_test_helpers" -require "./spec/support/stream_helpers" + +# External Libraries +require "active_support/core_ext/string/strip" + +# This library +require "support/dependency_helpers" +require "support/acceptance_test_helpers" +require "support/stream_helpers" + PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..")).freeze TMP_GEM_ROOT = File.join(PROJECT_ROOT, "tmp", "bundler") diff --git a/spec/support/acceptance_test_helpers.rb b/spec/support/acceptance_test_helpers.rb index d577580d..6db7fbc1 100644 --- a/spec/support/acceptance_test_helpers.rb +++ b/spec/support/acceptance_test_helpers.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true +# External Libraries require "rspec/expectations/expectation_target" -require "active_support/core_ext/string/strip" require "active_support/core_ext/string/filters" require "active_support/concern" + +# This library require "appraisal/utils" -require "./spec/support/dependency_helpers" module AcceptanceTestHelpers extend ActiveSupport::Concern @@ -91,7 +92,7 @@ def add_gemspec_to_gemfile end def build_gemspec - write_file "stage.gemspec", <<-GEMSPEC + write_file "stage.gemspec", <<-GEMSPEC.strip_heredoc Gem::Specification.new do |s| s.name = 'stage' s.version = '0.1' @@ -141,9 +142,9 @@ def ensure_bundler_is_available return unless $?.exitstatus != 0 - puts <<-WARNING.squish.strip_heredoc - Reinstall Bundler to #{TMP_GEM_ROOT} as `BUNDLE_DISABLE_SHARED_GEMS` - is enabled. + puts <<-WARNING.strip_heredoc + Reinstall Bundler to #{TMP_GEM_ROOT} as `BUNDLE_DISABLE_SHARED_GEMS` + is enabled. WARNING version = Utils.bundler_version @@ -151,16 +152,10 @@ def ensure_bundler_is_available end def build_default_gemfile - build_gemfile <<-GEMFILE + build_gemfile <<-GEMFILE.strip_heredoc source 'https://rubygems.org' gem 'appraisal', :path => '#{PROJECT_ROOT}' - - if RUBY_VERSION < "1.9" - #{File.read(File.join(PROJECT_ROOT, "Gemfile-1.8"))} - elsif RUBY_VERSION < "2.2" - #{File.read(File.join(PROJECT_ROOT, "Gemfile-2.1"))} - end GEMFILE run "bundle install --local" @@ -185,7 +180,7 @@ def run(command, raise_on_error = true) puts output if ENV["VERBOSE"] if raise_on_error && exitstatus != 0 - raise <<-ERROR_MESSAGE.strip_heredoc.to_s + raise <<-ERROR_MESSAGE.strip_heredoc Command #{command.inspect} exited with status #{exitstatus}. Output: #{output.gsub(/^/, " ")} ERROR_MESSAGE diff --git a/spec/support/dependency_helpers.rb b/spec/support/dependency_helpers.rb index c8d21793..6dfbd3a8 100644 --- a/spec/support/dependency_helpers.rb +++ b/spec/support/dependency_helpers.rb @@ -13,7 +13,7 @@ def build_gem(gem_name, version = "1.0.0") lib_file = "lib/#{gem_name}.rb" File.open gemspec, "w" do |file| - file.puts <<-GEMSPEC + file.puts <<-GEMSPEC.strip_heredoc Gem::Specification.new do |s| s.name = #{gem_name.inspect} s.version = #{version.inspect} diff --git a/spec/support/stream_helpers.rb b/spec/support/stream_helpers.rb index 97c0240d..021dcc9f 100644 --- a/spec/support/stream_helpers.rb +++ b/spec/support/stream_helpers.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# External Libraries require "tempfile" module StreamHelpers From a19e70746cce6bdab027e914c62a497033af181c Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Fri, 21 Feb 2025 14:27:15 +0700 Subject: [PATCH 07/60] =?UTF-8?q?=F0=9F=9A=A8=20Address=20code=20review=20?= =?UTF-8?q?from=20@n-rodriguez?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - https://github.com/thoughtbot/appraisal/pull/250#discussion_r1964532654 --- .rspec | 1 + 1 file changed, 1 insertion(+) diff --git a/.rspec b/.rspec index bd5e0288..78b7894f 100644 --- a/.rspec +++ b/.rspec @@ -1,3 +1,4 @@ --format progress --color --require spec_helper +--warnings From e1673bc68efa29746e979c763fa84d8460972b5f Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Fri, 21 Feb 2025 15:13:38 +0700 Subject: [PATCH 08/60] =?UTF-8?q?=F0=9F=90=9B=20Fixes=20for=20Ruby=202.7?= =?UTF-8?q?=20compat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Differences in handling of whitespace between versions of Ruby are often seen as minor, and go unnoticed unless tests explicitly test white space as appraisal's test suite does. --- .github/workflows/main.yml | 9 - .rubocop_gradual.lock | 444 ++++++++++++++++-- .tool-versions | 2 +- lib/appraisal/bundler_dsl.rb | 16 +- lib/appraisal/command.rb | 10 +- lib/appraisal/conditional.rb | 12 +- lib/appraisal/git.rb | 26 +- lib/appraisal/group.rb | 12 +- lib/appraisal/path.rb | 26 +- lib/appraisal/platform.rb | 8 +- lib/appraisal/source.rb | 8 +- lib/appraisal/utils.rb | 6 +- ...als_file_bundler_dsl_compatibility_spec.rb | 18 +- .../bundle_with_custom_path_spec.rb | 6 +- spec/acceptance/bundle_without_spec.rb | 4 +- spec/acceptance/cli/clean_spec.rb | 2 +- spec/acceptance/cli/generate_spec.rb | 6 +- spec/acceptance/cli/help_spec.rb | 2 +- spec/acceptance/cli/install_spec.rb | 14 +- spec/acceptance/cli/list_spec.rb | 2 +- spec/acceptance/cli/run_spec.rb | 4 +- spec/acceptance/cli/update_spec.rb | 2 +- spec/acceptance/cli/with_no_arguments_spec.rb | 2 +- .../gemfile_dsl_compatibility_spec.rb | 20 +- spec/acceptance/gemspec_spec.rb | 10 +- spec/appraisal/appraisal_spec.rb | 4 +- spec/appraisal/customize_spec.rb | 2 +- spec/appraisal/dependency_list_spec.rb | 2 +- spec/appraisal/gemfile_spec.rb | 37 +- spec/spec_helper.rb | 1 - spec/support/acceptance_test_helpers.rb | 18 +- spec/support/dependency_helpers.rb | 96 ++-- 32 files changed, 642 insertions(+), 189 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 42377a64..f6743f86 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,15 +22,6 @@ jobs: - '3.1' - '3.0' - '2.7' - - '2.6' - - '2.5' - - '2.4' - - '2.3' - - '2.2' - - '2.1' - - '2.0' - - '1.9' - - '1.8' - 'head' - jruby - jruby-head diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 94dc799e..9629a5ec 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -1,8 +1,8 @@ { - "Gemfile:3311641552": [ - [19, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [21, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [23, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] + "Gemfile:2720967286": [ + [26, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [28, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [30, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] ], "bin/bundle:3123891436": [ [66, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] @@ -18,35 +18,35 @@ [17, 5, 62, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 4082816720], [21, 5, 516, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2780620929] ], - "lib/appraisal/utils.rb:2308689703": [ + "lib/appraisal/utils.rb:3242656341": [ [6, 5, 129, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 733338411], [13, 5, 354, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 119295155], [35, 5, 152, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1306460482], [42, 5, 151, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1120325158], - [48, 5, 97, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2744794681], + [48, 5, 98, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 714993131], [52, 5, 244, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1461524090], [61, 5, 111, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1909626476] ], - "spec/acceptance/cli/clean_spec.rb:1398207731": [ - [5, 23, 17, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 1606893221] + "spec/acceptance/cli/clean_spec.rb:1564995421": [ + [3, 23, 17, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 1606893221] ], - "spec/acceptance/cli/generate_spec.rb:1599585127": [ - [5, 23, 20, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3905826443] + "spec/acceptance/cli/generate_spec.rb:245350726": [ + [3, 23, 20, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3905826443] ], - "spec/acceptance/cli/help_spec.rb:3832542771": [ - [5, 23, 16, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 2148351217] + "spec/acceptance/cli/help_spec.rb:3569358941": [ + [3, 23, 16, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 2148351217] ], - "spec/acceptance/cli/install_spec.rb:2827187127": [ - [5, 23, 19, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3284642881] + "spec/acceptance/cli/install_spec.rb:1306756550": [ + [3, 23, 19, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3284642881] ], - "spec/acceptance/cli/list_spec.rb:1943273700": [ - [5, 23, 16, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 2152687586] + "spec/acceptance/cli/list_spec.rb:36921834": [ + [3, 23, 16, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 2152687586] ], - "spec/acceptance/cli/update_spec.rb:2524405540": [ - [5, 23, 18, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3752509585] + "spec/acceptance/cli/update_spec.rb:3754424074": [ + [3, 23, 18, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3752509585] ], - "spec/acceptance/cli/version_spec.rb:4076882072": [ - [5, 23, 19, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 316256858] + "spec/acceptance/cli/version_spec.rb:2850459497": [ + [3, 23, 19, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 316256858] ], "spec/appraisal/appraisal_file_spec.rb:1896479557": [ [28, 18, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], @@ -59,7 +59,7 @@ [57, 7, 77, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1960750461], [65, 11, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] ], - "spec/appraisal/appraisal_spec.rb:1242607413": [ + "spec/appraisal/appraisal_spec.rb:3939376245": [ [33, 11, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2511581329], [90, 11, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1120511218], [95, 7, 83, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [96].", 1453890366], @@ -72,8 +72,8 @@ [120, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], [126, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192] ], - "spec/appraisal/customize_spec.rb:1577209079": [ - [7, 1, 4439, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 3030165271], + "spec/appraisal/customize_spec.rb:3636242792": [ + [7, 1, 4472, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 194570577], [17, 3, 13, "RSpec/SubjectDeclaration: Use subject explicitly rather than using let", 3282510975], [25, 3, 564, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 3336288078], [27, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], @@ -86,26 +86,392 @@ [68, 7, 85, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 66, 67].", 3874694796], [72, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] ], - "spec/appraisal/gemfile_spec.rb:3323881535": [ - [227, 11, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3608128140], - [228, 13, 13, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 420381022], - [235, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3511037132], - [245, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3100155342], - [255, 11, 24, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3242693747], - [258, 13, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 105800534], - [281, 13, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 179066369], - [312, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3912615366], - [356, 13, 14, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2832187185], - [414, 13, 22, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 772581599], - [424, 11, 20, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1076107314] + "spec/appraisal/gemfile_spec.rb:2644921119": [ + [228, 11, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3608128140], + [229, 13, 13, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 420381022], + [236, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3511037132], + [246, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3100155342], + [256, 11, 24, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3242693747], + [259, 13, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 105800534], + [282, 13, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 179066369], + [313, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3912615366], + [357, 13, 14, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2832187185], + [415, 13, 22, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 772581599], + [425, 11, 20, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1076107314] ], "spec/appraisal/utils_spec.rb:2286225770": [ [62, 17, 58, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 1573223692] ], - "spec/support/acceptance_test_helpers.rb:1261310616": [ - [133, 5, 32, "Style/InvertibleUnlessCondition: Prefer `if $?.exitstatus == 0` over `unless $?.exitstatus != 0`.", 4187517264] + "spec/support/acceptance_test_helpers.rb:293636491": [ + [143, 5, 32, "Style/InvertibleUnlessCondition: Prefer `if $?.exitstatus == 0` over `unless $?.exitstatus != 0`.", 4187517264] ], - "spec/support/stream_helpers.rb:3273310040": [ - [9, 17, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] + "spec/support/stream_helpers.rb:3654818709": [ + [10, 17, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] + ], + "spec/tmp/build/bagel/lib/bagel.rb:817034159": [ + [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 93522089] + ], + "spec/tmp/build/coffee/lib/coffee.rb:3015295950": [ + [1, 1, 15, "Style/GlobalVars: Do not introduce global variables.", 1715453096] + ], + "spec/tmp/build/croissant/lib/croissant.rb:4104237646": [ + [1, 1, 18, "Style/GlobalVars: Do not introduce global variables.", 2226371368] + ], + "spec/tmp/build/dummy/lib/dummy.rb:1807990539": [ + [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 2877655148] + ], + "spec/tmp/build/egg/lib/egg.rb:3130854087": [ + [1, 1, 12, "Style/GlobalVars: Do not introduce global variables.", 4028848065] + ], + "spec/tmp/build/ham/lib/ham.rb:557050406": [ + [1, 1, 12, "Style/GlobalVars: Do not introduce global variables.", 1287500928] + ], + "spec/tmp/build/mayonnaise/lib/mayonnaise.rb:604109062": [ + [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 3499390688] + ], + "spec/tmp/build/milk/lib/milk.rb:2694353217": [ + [1, 1, 13, "Style/GlobalVars: Do not introduce global variables.", 3069591303] + ], + "spec/tmp/build/omelette/lib/omelette.rb:3378185993": [ + [1, 1, 17, "Style/GlobalVars: Do not introduce global variables.", 576262095] + ], + "spec/tmp/build/orange_juice/lib/orange_juice.rb:3578149981": [ + [1, 1, 21, "Style/GlobalVars: Do not introduce global variables.", 1923934619] + ], + "spec/tmp/build/pain_au_chocolat/lib/pain_au_chocolat.rb:2551039889": [ + [1, 1, 25, "Style/GlobalVars: Do not introduce global variables.", 2391071575] + ], + "spec/tmp/build/pancake/lib/pancake.rb:284512849": [ + [1, 1, 16, "Style/GlobalVars: Do not introduce global variables.", 451124759] + ], + "spec/tmp/build/rotten_egg/lib/rotten_egg.rb:2010666510": [ + [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 2573678312] + ], + "spec/tmp/build/sausage/lib/sausage.rb:1728262677": [ + [1, 1, 16, "Style/GlobalVars: Do not introduce global variables.", 619820115] + ], + "spec/tmp/build/soda/lib/soda.rb:1990629979": [ + [1, 1, 13, "Style/GlobalVars: Do not introduce global variables.", 198441437] + ], + "spec/tmp/build/waffle/lib/waffle.rb:2896717917": [ + [1, 1, 15, "Style/GlobalVars: Do not introduce global variables.", 2356319643] + ], + "spec/tmp/bundler/bin/appraisal:662174372": [ + [18, 10, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] + ], + "spec/tmp/bundler/bin/rake:3146010916": [ + [18, 10, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] + ], + "spec/tmp/bundler/bin/thor:4227855012": [ + [18, 10, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] + ], + "spec/tmp/bundler/gems/bagel-1.0.0/lib/bagel.rb:817034159": [ + [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 93522089] + ], + "spec/tmp/bundler/gems/coffee-1.0.0/lib/coffee.rb:3015295950": [ + [1, 1, 15, "Style/GlobalVars: Do not introduce global variables.", 1715453096] + ], + "spec/tmp/bundler/gems/dummy-1.0.0/lib/dummy.rb:1804502538": [ + [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 2877655148] + ], + "spec/tmp/bundler/gems/dummy-1.1.0/lib/dummy.rb:1807990539": [ + [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 2877655148] + ], + "spec/tmp/bundler/gems/ham-1.0.0/lib/ham.rb:557050406": [ + [1, 1, 12, "Style/GlobalVars: Do not introduce global variables.", 1287500928] + ], + "spec/tmp/bundler/gems/mayonnaise-1.0.0/lib/mayonnaise.rb:604109062": [ + [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 3499390688] + ], + "spec/tmp/bundler/gems/milk-1.0.0/lib/milk.rb:2694353217": [ + [1, 1, 13, "Style/GlobalVars: Do not introduce global variables.", 3069591303] + ], + "spec/tmp/bundler/gems/orange_juice-1.0.0/lib/orange_juice.rb:3578149981": [ + [1, 1, 21, "Style/GlobalVars: Do not introduce global variables.", 1923934619] + ], + "spec/tmp/bundler/gems/pancake-1.0.0/lib/pancake.rb:284512849": [ + [1, 1, 16, "Style/GlobalVars: Do not introduce global variables.", 451124759] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake.rb:3015112320": [ + [64, 1, 6, "Style/GlobalVars: Do not introduce global variables.", 3075757472] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/application.rb:3305321773": [ + [63, 21, 6, "Style/GlobalStdStream: Use `$stdout` instead of `STDOUT`.", 3356722952], + [113, 13, 6, "Style/GlobalStdStream: Use `$stderr` instead of `STDERR`.", 3356712163], + [222, 11, 5, "Lint/Loop: Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`).", 191284826], + [236, 5, 122, "Lint/RescueException: Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?", 3552754902], + [305, 65, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [306, 50, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [514, 15, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [523, 20, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [530, 40, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [532, 30, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [537, 78, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [553, 40, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [608, 59, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [638, 54, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [647, 66, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [656, 53, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [664, 60, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [671, 62, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [672, 46, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [681, 71, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [798, 24, 2, "Style/AndOr: Use `||` instead of `or`.", 5861240], + [889, 16, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560], + [895, 20, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560], + [895, 33, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/backtrace.rb:2947413644": [ + [16, 43, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806], + [20, 5, 182, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 684235907] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/clean.rb:597197225": [ + [47, 18, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/cpu_counter.rb:114869078": [ + [7, 5, 51, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1633217579] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/ext/core.rb:37720573": [ + [21, 71, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/file_utils.rb:1092133475": [ + [67, 68, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/file_utils_ext.rb:1080867503": [ + [15, 7, 42, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 598600538] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/invocation_chain.rb:2990720762": [ + [27, 5, 73, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 669377266] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/linked_list.rb:3208307164": [ + [59, 5, 439, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3263738083], + [73, 5, 55, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2265797213], + [78, 5, 40, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 201197260], + [105, 7, 68, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1829672226], + [106, 9, 7, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1309332345] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/private_reader.rb:670493723": [ + [6, 5, 63, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2901108034] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/promise.rb:910582": [ + [65, 7, 40, "Lint/RescueException: Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?", 3824424681] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/rake_module.rb:4177774778": [ + [9, 7, 12, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 4135892607], + [13, 5, 24, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 2330715366], + [16, 7, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2063727135], + [17, 7, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2063727135] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/task.rb:825529577": [ + [220, 9, 116, "Lint/RescueException: Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?", 3582047834], + [278, 15, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560], + [278, 40, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806], + [373, 5, 137, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2016900957] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/task_arguments.rb:2422589739": [ + [66, 5, 63, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 2216682504] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/task_manager.rb:988246897": [ + [27, 31, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806], + [136, 9, 18, "Style/IdenticalConditionalBranches: Move `deps = value || []` out of the conditional.", 3582664887], + [140, 9, 18, "Style/IdenticalConditionalBranches: Move `deps = value || []` out of the conditional.", 3582664887], + [278, 22, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560], + [326, 7, 35, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 402700679] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/testtask.rb:431563537": [ + [112, 48, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [121, 51, 2, "Style/AndOr: Use `||` instead of `or`.", 5861240] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/thread_pool.rb:12277952": [ + [48, 9, 530, "Lint/RescueException: Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?", 228964421], + [51, 65, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [53, 70, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [116, 9, 48, "Style/InvertibleUnlessCondition: Prefer `if @threads.count >= @max_active_threads` over `unless @threads.count < @max_active_threads`.", 2403143961], + [118, 13, 10, "ThreadSafety/NewThread: Avoid starting new threads.", 3411682361] + ], + "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/win32.rb:4149036273": [ + [40, 36, 2, "Style/AndOr: Use `||` instead of `or`.", 5861240] + ], + "spec/tmp/bundler/gems/rake-13.2.1/rake.gemspec:2780653655": [ + [12, 19, 2, "Lint/Syntax: unexpected token tLSHFT\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5859461], + [13, 25, 7, "Lint/Syntax: unexpected token tIDENTIFIER\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 1804902097], + [14, 15, 2, "Lint/Syntax: unexpected token kIN\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5861154], + [16, 7, 1, "Lint/Syntax: unexpected token tSTAR\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177551], + [16, 24, 1, "Lint/Syntax: unterminated string meets end of file\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177538] + ], + "spec/tmp/bundler/gems/rotten_egg-1.0.0/lib/rotten_egg.rb:2010666510": [ + [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 2573678312] + ], + "spec/tmp/bundler/gems/sausage-1.0.0/lib/sausage.rb:1728262677": [ + [1, 1, 16, "Style/GlobalVars: Do not introduce global variables.", 619820115] + ], + "spec/tmp/bundler/gems/soda-1.0.0/lib/soda.rb:1990629979": [ + [1, 1, 13, "Style/GlobalVars: Do not introduce global variables.", 198441437] + ], + "spec/tmp/bundler/gems/thor-1.3.2/bin/thor:1678810035": [ + [5, 1, 12, "Style/GlobalVars: Do not introduce global variables.", 2230010895] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor.rb:333295015": [ + [4, 3, 12, "Style/GlobalVars: Do not introduce global variables.", 2230010895], + [13, 7, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 551240135], + [23, 9, 16, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 580261046], + [25, 9, 16, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 580261046], + [39, 9, 32, "Style/IdenticalConditionalBranches: Move `desc usage, description, options` out of the conditional.", 4209929479], + [42, 9, 32, "Style/IdenticalConditionalBranches: Move `desc usage, description, options` out of the conditional.", 4209929479], + [60, 9, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], + [61, 9, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], + [62, 9, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213880165], + [83, 9, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2420967073], + [84, 9, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1012447818], + [102, 7, 4, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2088878297], + [112, 33, 4, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2088878297], + [114, 13, 4, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2088878297], + [119, 7, 4, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2088878297], + [130, 7, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797], + [131, 30, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797], + [132, 7, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797], + [303, 19, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 551240135], + [303, 37, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 551240135], + [304, 22, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 551240135], + [329, 7, 12, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3952225397], + [334, 7, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2063673473], + [359, 7, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], + [362, 11, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], + [364, 11, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], + [367, 7, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], + [429, 7, 23, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 288545224], + [443, 7, 23, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2342089118], + [458, 7, 60, "Performance/InefficientHashSearch: Use `#key?` instead of `#keys.include?`.", 675081132], + [469, 7, 30, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 747165948], + [478, 7, 33, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2836932844], + [482, 7, 23, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 288545224], + [487, 7, 23, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2342089118], + [555, 37, 12, "Style/GlobalVars: Do not introduce global variables.", 2230010895], + [569, 7, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], + [570, 7, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], + [571, 7, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2420967073], + [572, 7, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1012447818], + [573, 7, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213880165], + [575, 10, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], + [575, 20, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], + [576, 22, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213880165], + [581, 47, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], + [581, 54, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2420967073], + [581, 66, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1012447818], + [581, 83, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], + [582, 9, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], + [582, 17, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], + [582, 24, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2420967073], + [582, 36, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1012447818], + [582, 53, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797], + [582, 70, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213880165], + [583, 9, 30, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 747165948], + [583, 41, 33, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2836932844], + [598, 7, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/actions.rb:1169132954": [ + [12, 5, 84, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3488611255], + [23, 9, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3359610630], + [28, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3225348734], + [29, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3225348734], + [238, 13, 4, "Security/Open: The use of `URI.open` is a serious security risk.", 2087926481] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/base.rb:1396078371": [ + [42, 50, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [143, 9, 11, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3739410329], + [152, 9, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 510344549], + [183, 9, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], + [187, 9, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], + [198, 9, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], + [204, 9, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], + [208, 9, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], + [208, 89, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], + [209, 9, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], + [229, 9, 21, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3536149808], + [233, 9, 21, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3536149808], + [308, 9, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 4021964389], + [321, 9, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1127210468], + [322, 32, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1127210468], + [323, 9, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1127210468], + [425, 9, 29, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2816325805], + [434, 9, 32, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 20048093], + [481, 11, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2748649178], + [483, 11, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2748649178], + [494, 9, 9, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 941479953], + [505, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 461316431], + [506, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 461316431], + [559, 9, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1160282543], + [590, 11, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2076032070], + [592, 11, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2076032070], + [635, 60, 12, "Style/GlobalVars: Do not introduce global variables.", 2230010895] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/core_ext/hash_with_indifferent_access.rb:1816584307": [ + [93, 7, 265, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 3153843738] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/group.rb:919076424": [ + [18, 9, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], + [20, 9, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], + [40, 7, 12, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2641829910], + [46, 7, 18, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1958067488], + [222, 7, 36, "Performance/InefficientHashSearch: Use `#key?` instead of `#keys.include?`.", 1233002216] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/invocation.rb:15277192": [ + [3, 5, 84, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3488611255], + [113, 7, 68, "Style/InvertibleUnlessCondition: Prefer `if klass > Thor::Base` over `unless klass <= Thor::Base`.", 323464394] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/line_editor.rb:445051654": [ + [6, 5, 98, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1722966001], + [10, 5, 137, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3807720162] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/line_editor/basic.rb:2990814377": [ + [6, 7, 42, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2226661248] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/line_editor/readline.rb:2639491563": [ + [4, 7, 151, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1555432841], + [17, 23, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/parser/argument.rb:1757849163": [ + [28, 26, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/parser/arguments.rb:2060486072": [ + [8, 5, 220, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3264205835], + [19, 5, 88, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 64145645] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/parser/option.rb:3720922756": [ + [45, 5, 707, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 4238798220], + [153, 48, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], + [154, 118, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/parser/options.rb:1590095627": [ + [11, 5, 417, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1097829481] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/rake_compat.rb:2680359318": [ + [23, 5, 56, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 120645003], + [24, 7, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 514624543], + [27, 5, 291, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 289349924] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/runner.rb:1283721011": [ + [11, 3, 124, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1462699376], + [15, 3, 40, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3579960], + [35, 3, 308, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 2830630606], + [56, 24, 4, "Security/Open: The use of `URI.open` is a serious security risk.", 2087926481], + [72, 26, 4, "Security/Open: The use of `URI.open` is a serious security risk.", 2087926481], + [227, 64, 60, "Performance/InefficientHashSearch: Use `#key?` instead of `#keys.include?`.", 552387362] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/shell.rb:4091723221": [ + [6, 7, 18, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 3758912994], + [12, 9, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2772268155] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/shell/terminal.rb:3147912038": [ + [28, 11, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3528096361] + ], + "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/util.rb:1633474373": [ + [222, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 4258999585] + ], + "spec/tmp/bundler/gems/waffle-1.0.0/lib/waffle.rb:2896717917": [ + [1, 1, 15, "Style/GlobalVars: Do not introduce global variables.", 2356319643] + ], + "spec/tmp/bundler/specifications/thor-1.3.2.gemspec:4209767878": [ + [24, 3, 79, "Gemspec/DependencyVersion: Dependency version specification is required.", 2841802434] ] } diff --git a/.tool-versions b/.tool-versions index 59511e1d..973bb631 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 2.7.8 +`ruby 3.4.2 diff --git a/lib/appraisal/bundler_dsl.rb b/lib/appraisal/bundler_dsl.rb index b3c87042..1419e8ca 100644 --- a/lib/appraisal/bundler_dsl.rb +++ b/lib/appraisal/bundler_dsl.rb @@ -162,7 +162,21 @@ def #{method_name}_entry_for_dup end def indent(string) - string.strip.gsub(/^(.+)$/, ' \1') + indent_by = ENV.fetch("APPRAISAL_INDENTER", "lookahead") + if indent_by == "lookahead" + # Default indenter for Appraisal v3 + # Uses a look-ahead to indent lines that start with a "word" (as defined by RegExp) + # (optionally preceded by whitespace). + # First it finds the point where the white space ends / words starts, + # and inserts two spaces at that point, leaving any existing whitespace in place. + # In other words, retain existing indentation, and indent the line again. + string.gsub(/^(?=(\s*)\w)/, " ").rstrip + elsif indent_by == "capture" + # Original indentation regex for Appraisal < v3 + string.gsub(/^(.+)$/, ' \1').rstrip + else + string + end end def substitute_git_source(requirements) diff --git a/lib/appraisal/command.rb b/lib/appraisal/command.rb index dd29ea44..14c2718e 100644 --- a/lib/appraisal/command.rb +++ b/lib/appraisal/command.rb @@ -41,11 +41,11 @@ def ensure_bundler_is_available return if system("gem install bundler --version #{version}") puts - puts <<-ERROR.strip_heredoc - Bundler installation failed. - Please try running: - `GEM_HOME="#{ENV["GEM_HOME"]}" gem install bundler --version #{version}` - manually. + puts <<-ERROR.rstrip +Bundler installation failed. +Please try running: + `GEM_HOME="#{ENV["GEM_HOME"]}" gem install bundler --version #{version}` +manually. ERROR exit(1) end diff --git a/lib/appraisal/conditional.rb b/lib/appraisal/conditional.rb index ad2a8e1a..1056cded 100644 --- a/lib/appraisal/conditional.rb +++ b/lib/appraisal/conditional.rb @@ -11,14 +11,22 @@ def initialize(condition) end def to_s - "install_if #{@condition} do\n#{indent(super)}\nend" + <<-OUTPUT.rstrip +install_if #{@condition} do +#{indent(super)} +end + OUTPUT end # :nodoc: def for_dup return unless @condition.is_a?(String) - "install_if #{@condition} do\n#{indent(super)}\nend" + <<-OUTPUT.rstrip +install_if #{@condition} do +#{indent(super)} +end + OUTPUT end end end diff --git a/lib/appraisal/git.rb b/lib/appraisal/git.rb index 791429df..e7dd6aae 100644 --- a/lib/appraisal/git.rb +++ b/lib/appraisal/git.rb @@ -13,20 +13,34 @@ def initialize(source, options = {}) def to_s if @options.empty? - "git #{Utils.prefix_path(@source).inspect} do\n#{indent(super)}\nend" + <<-OUTPUT.rstrip +git #{Utils.prefix_path(@source).inspect} do +#{indent(super)} +end + OUTPUT else - "git #{Utils.prefix_path(@source).inspect}, #{Utils.format_string(@options)} do\n" \ - "#{indent(super)}\nend" + <<-OUTPUT.rstrip +git #{Utils.prefix_path(@source).inspect}, #{Utils.format_string(@options)} do +#{indent(super)} +end + OUTPUT end end # :nodoc: def for_dup if @options.empty? - "git #{@source.inspect} do\n#{indent(super)}\nend" + <<-OUTPUT.rstrip +git #{@source.inspect} do +#{indent(super)} +end + OUTPUT else - "git #{@source.inspect}, #{Utils.format_string(@options)} do\n" \ - "#{indent(super)}\nend" + <<-OUTPUT.rstrip +git #{@source.inspect}, #{Utils.format_string(@options)} do +#{indent(super)} +end + OUTPUT end end end diff --git a/lib/appraisal/group.rb b/lib/appraisal/group.rb index f1f82314..6517d914 100644 --- a/lib/appraisal/group.rb +++ b/lib/appraisal/group.rb @@ -11,21 +11,21 @@ def initialize(group_names) end def to_s - formatted_output(indent(super)) + formatted_output(super) end # :nodoc: def for_dup - formatted_output(indent(super)) + formatted_output(super) end private def formatted_output(output_dependencies) - <<-OUTPUT.strip_heredoc - group #{Utils.format_arguments(@group_names)} do - #{output_dependencies} - end + <<-OUTPUT.rstrip +group #{Utils.format_arguments(@group_names)} do +#{indent(output_dependencies)} +end OUTPUT end end diff --git a/lib/appraisal/path.rb b/lib/appraisal/path.rb index c33b60c6..42be91b7 100644 --- a/lib/appraisal/path.rb +++ b/lib/appraisal/path.rb @@ -13,20 +13,34 @@ def initialize(source, options = {}) def to_s if @options.empty? - "path #{Utils.prefix_path(@source).inspect} do\n#{indent(super)}\nend" + <<-OUTPUT.rstrip +path #{Utils.prefix_path(@source).inspect} do +#{indent(super)} +end + OUTPUT else - "path #{Utils.prefix_path(@source).inspect}, #{Utils.format_string(@options)} do\n" \ - "#{indent(super)}\nend" + <<-OUTPUT.rstrip +path #{Utils.prefix_path(@source).inspect}, #{Utils.format_string(@options)} do +#{indent(super)} +end" + OUTPUT end end # :nodoc: def for_dup if @options.empty? - "path #{@source.inspect} do\n#{indent(super)}\nend" + <<-OUTPUT.rstrip +path #{@source.inspect} do +#{indent(super)} +end + OUTPUT else - "path #{@source.inspect}, #{Utils.format_string(@options)} do\n" \ - "#{indent(super)}\nend" + <<-OUTPUT.rstrip +path #{@source.inspect}, #{Utils.format_string(@options)} do +#{indent(super)} +end + OUTPUT end end end diff --git a/lib/appraisal/platform.rb b/lib/appraisal/platform.rb index ae0e0849..9b8cc553 100644 --- a/lib/appraisal/platform.rb +++ b/lib/appraisal/platform.rb @@ -11,20 +11,20 @@ def initialize(platform_names) end def to_s - formatted_output(indent(super)) + formatted_output(super) end # :nodoc: def for_dup - formatted_output(indent(super)) + formatted_output(super) end private def formatted_output(output_dependencies) - <<-OUTPUT.strip + <<-OUTPUT.rstrip platforms #{Utils.format_arguments(@platform_names)} do -#{output_dependencies} +#{indent(output_dependencies)} end OUTPUT end diff --git a/lib/appraisal/source.rb b/lib/appraisal/source.rb index ebbe71e9..6c926a2d 100644 --- a/lib/appraisal/source.rb +++ b/lib/appraisal/source.rb @@ -11,20 +11,20 @@ def initialize(source) end def to_s - formatted_output(indent(super)) + formatted_output(super) end # :nodoc: def for_dup - formatted_output(indent(super)) + formatted_output(super) end private def formatted_output(output_dependencies) - <<-OUTPUT.strip + <<-OUTPUT.rstrip source #{@source.inspect} do -#{output_dependencies} +#{indent(output_dependencies)} end OUTPUT end diff --git a/lib/appraisal/utils.rb b/lib/appraisal/utils.rb index a9cf68e0..e0c455aa 100644 --- a/lib/appraisal/utils.rb +++ b/lib/appraisal/utils.rb @@ -7,6 +7,10 @@ def self.support_parallel_installation? Gem::Version.create(Bundler::VERSION) >= Gem::Version.create("1.4.0.pre.1") end + def self.support_git_local_installation? + Gem::Version.create(Bundler::VERSION) > Gem::Version.create("2.4.22") + end + # Appraisal needs to print Gemfiles in the oldest Ruby syntax that is supported by Appraisal. # Otherwise, a project would not be able to use Appraisal to test compatibility # with older versions of Ruby, which is a core use case for Appraisal. @@ -46,7 +50,7 @@ def self.format_arguments(arguments) end def self.join_parts(parts) - parts.reject(&:nil?).reject(&:empty?).join("\n\n").strip + parts.reject(&:nil?).reject(&:empty?).join("\n\n").rstrip end def self.prefix_path(path) diff --git a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb index 41e669ee..7112c55c 100644 --- a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb +++ b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true RSpec.describe "Appraisals file Bundler DSL compatibility" do - it "supports all Bundler DSL in Appraisals file" do + it "supports all Bundler DSL in Appraisals file", :git_local do build_gems %w[ bagel orange_juice @@ -16,7 +16,7 @@ ] build_git_gems %w[egg croissant pain_au_chocolat omelette] - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source 'https://rubygems.org' git_source(:custom_git_source) { |repo| "../build/\#{repo}" } ruby "#{RUBY_VERSION}#{ruby_dev_append}" @@ -57,7 +57,7 @@ gem 'appraisal', :path => #{PROJECT_ROOT.inspect} GEMFILE - build_appraisal_file <<-APPRAISALS.strip_heredoc + build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip appraise 'breakfast' do source 'http://some-other-source.com' ruby "1.8.7" @@ -102,7 +102,7 @@ run "bundle install --local" run "appraisal generate" - expect(content_of("gemfiles/breakfast.gemfile")).to eq <<-GEMFILE.strip_heredoc + expect(content_of("gemfiles/breakfast.gemfile")).to eq <<-GEMFILE.strip_heredoc.rstrip # This file was generated by Appraisal source "https://rubygems.org" @@ -130,7 +130,7 @@ gem "orange_juice" gem "omelette", :git => "../../build/omelette" gem "bacon" - + platforms :rbx do gem "ham" end @@ -139,7 +139,7 @@ platforms :ruby, :jruby do gem "milk" gem "yoghurt" - + group :lunch do gem "coffee" end @@ -161,7 +161,7 @@ end it 'supports ruby file: ".ruby-version" DSL' do - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source 'https://rubygems.org' ruby "#{RUBY_VERSION}#{ruby_dev_append}" @@ -169,7 +169,7 @@ gem 'appraisal', :path => #{PROJECT_ROOT.inspect} GEMFILE - build_appraisal_file <<-APPRAISALS.strip_heredoc + build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip appraise 'ruby-version' do ruby({:file => ".ruby-version"}) end @@ -178,7 +178,7 @@ run "bundle install --local" run "appraisal generate" - expect(content_of("gemfiles/ruby_version.gemfile")).to eq <<-GEMFILE.strip_heredoc + expect(content_of("gemfiles/ruby_version.gemfile")).to eq <<-GEMFILE.strip_heredoc.rstrip # This file was generated by Appraisal source "https://rubygems.org" diff --git a/spec/acceptance/bundle_with_custom_path_spec.rb b/spec/acceptance/bundle_with_custom_path_spec.rb index bb6fca1b..f459723c 100644 --- a/spec/acceptance/bundle_with_custom_path_spec.rb +++ b/spec/acceptance/bundle_with_custom_path_spec.rb @@ -6,7 +6,7 @@ shared_examples "gemfile dependencies are satisfied" do it "installs gems in the --path directory" do - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" gem 'appraisal', :path => #{PROJECT_ROOT.inspect} @@ -18,7 +18,7 @@ end GEMFILE - build_appraisal_file <<-APPRAISALS.strip_heredoc + build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip appraise "#{gem_name}" do gem '#{gem_name}' end @@ -47,7 +47,7 @@ context "when already installed in vendor/another" do before do - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" if RUBY_VERSION <= "1.9" diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index 8960e031..fbe5ad31 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -5,7 +5,7 @@ pending "config set --local without group support seems broken, see: https://github.com/rubygems/rubygems/issues/8518" build_gems %w[pancake orange_juice waffle coffee sausage soda] - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" gem "pancake" @@ -18,7 +18,7 @@ gem "appraisal", :path => #{PROJECT_ROOT.inspect} GEMFILE - build_appraisal_file <<-APPRAISALS.strip_heredoc + build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip appraise "breakfast" do gem "waffle" diff --git a/spec/acceptance/cli/clean_spec.rb b/spec/acceptance/cli/clean_spec.rb index 164dc3f4..45742a1e 100644 --- a/spec/acceptance/cli/clean_spec.rb +++ b/spec/acceptance/cli/clean_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "CLI", "appraisal clean" do it "remove all gemfiles from gemfiles directory" do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/generate_spec.rb b/spec/acceptance/cli/generate_spec.rb index 0c7eb454..9c6fdb50 100644 --- a/spec/acceptance/cli/generate_spec.rb +++ b/spec/acceptance/cli/generate_spec.rb @@ -2,13 +2,13 @@ RSpec.describe "CLI", "appraisal generate" do it "generates the gemfiles" do - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" gem "appraisal", :path => "#{PROJECT_ROOT}" GEMFILE - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -22,7 +22,7 @@ expect(file("gemfiles/1.0.0.gemfile")).to be_exists expect(file("gemfiles/1.1.0.gemfile")).to be_exists - expect(content_of("gemfiles/1.0.0.gemfile")).to eq <<-GEMFILE.strip_heredoc + expect(content_of("gemfiles/1.0.0.gemfile")).to eq <<-GEMFILE.strip_heredoc.rstrip # This file was generated by Appraisal source "https://rubygems.org" diff --git a/spec/acceptance/cli/help_spec.rb b/spec/acceptance/cli/help_spec.rb index 45bc1e03..96524545 100644 --- a/spec/acceptance/cli/help_spec.rb +++ b/spec/acceptance/cli/help_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "CLI", "appraisal help" do it "prints usage along with commands, and list of appraisals" do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/install_spec.rb b/spec/acceptance/cli/install_spec.rb index f92405ce..3fad1102 100644 --- a/spec/acceptance/cli/install_spec.rb +++ b/spec/acceptance/cli/install_spec.rb @@ -8,7 +8,7 @@ end it "installs the dependencies" do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -28,7 +28,7 @@ build_gemspec add_gemspec_to_gemfile - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -39,7 +39,7 @@ expect(content_of("gemfiles/1.0.0.gemfile.lock")).not_to include(current_directory) end - it "does not relativize directory of uris in gemfile.lock" do + it "does not relativize directory of uris in gemfile.lock", :git_local do build_gemspec add_gemspec_to_gemfile @@ -47,7 +47,7 @@ uri_dummy_path = "#{current_directory}/uri_dummy" FileUtils.symlink(File.absolute_path("tmp/build/uri_dummy"), uri_dummy_path) - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'uri_dummy', git: 'file://#{uri_dummy_path}' end @@ -60,7 +60,7 @@ context "with job size", :parallel do before do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -84,7 +84,7 @@ context "with full-index", :parallel do before do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -100,7 +100,7 @@ context "with path", :parallel do before do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/list_spec.rb b/spec/acceptance/cli/list_spec.rb index e2777e17..7bf1379b 100644 --- a/spec/acceptance/cli/list_spec.rb +++ b/spec/acceptance/cli/list_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "CLI", "appraisal list" do it "prints list of appraisals" do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/cli/run_spec.rb b/spec/acceptance/cli/run_spec.rb index d0fd1ab9..19825462 100644 --- a/spec/acceptance/cli/run_spec.rb +++ b/spec/acceptance/cli/run_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "CLI appraisal (with arguments)" do before do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end @@ -18,7 +18,7 @@ end it "sets APPRAISAL_INITIALIZED environment variable" do - write_file "test.rb", <<-TEST_FILE.strip_heredoc + write_file "test.rb", <<-TEST_FILE.strip_heredoc.rstrip if ENV['APPRAISAL_INITIALIZED'] puts "Appraisal initialized!" end diff --git a/spec/acceptance/cli/update_spec.rb b/spec/acceptance/cli/update_spec.rb index be66063b..61fe1611 100644 --- a/spec/acceptance/cli/update_spec.rb +++ b/spec/acceptance/cli/update_spec.rb @@ -4,7 +4,7 @@ before do build_gem "dummy2", "1.0.0" - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise 'dummy' do gem 'dummy', '~> 1.0.0' gem 'dummy2', '~> 1.0.0' diff --git a/spec/acceptance/cli/with_no_arguments_spec.rb b/spec/acceptance/cli/with_no_arguments_spec.rb index 962a9bb1..5a5e9f4d 100644 --- a/spec/acceptance/cli/with_no_arguments_spec.rb +++ b/spec/acceptance/cli/with_no_arguments_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "CLI appraisal (with no arguments)" do it "runs install command" do - build_appraisal_file <<-APPRAISAL.strip_heredoc + build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip appraise '1.0.0' do gem 'dummy', '1.0.0' end diff --git a/spec/acceptance/gemfile_dsl_compatibility_spec.rb b/spec/acceptance/gemfile_dsl_compatibility_spec.rb index c2987251..6e802218 100644 --- a/spec/acceptance/gemfile_dsl_compatibility_spec.rb +++ b/spec/acceptance/gemfile_dsl_compatibility_spec.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true RSpec.describe "Gemfile DSL compatibility" do - it "supports all Bundler DSL in Gemfile" do + it "supports all Bundler DSL in Gemfile", :git_local do build_gems %w[bacon orange_juice waffle] build_git_gem "egg" build_gemspec - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" ruby "#{RUBY_VERSION}#{ruby_dev_append}" @@ -31,7 +31,7 @@ gemspec GEMFILE - build_appraisal_file <<-APPRAISALS.strip_heredoc + build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip appraise "japanese" do gem "rice" gem "miso_soup" @@ -45,7 +45,7 @@ run "bundle install --local" run "appraisal generate" - expect(content_of("gemfiles/japanese.gemfile")).to eq <<-GEMFILE.strip_heredoc + expect(content_of("gemfiles/japanese.gemfile")).to eq <<-GEMFILE.strip_heredoc.rstrip # This file was generated by Appraisal source "https://rubygems.org" @@ -75,7 +75,7 @@ gemspec :path => "../" GEMFILE - expect(content_of("gemfiles/english.gemfile")).to eq <<-GEMFILE.strip_heredoc + expect(content_of("gemfiles/english.gemfile")).to eq <<-GEMFILE.strip_heredoc.rstrip # This file was generated by Appraisal source "https://rubygems.org" @@ -110,14 +110,14 @@ build_gem "bacon", "1.1.0" build_gem "bacon", "1.2.0" - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" gem "appraisal", :path => #{PROJECT_ROOT.inspect} gem "bacon", "1.2.0" GEMFILE - build_appraisal_file <<-APPRAISALS.strip_heredoc + build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip appraise "1.0.0" do gem "bacon", "1.0.0" end @@ -143,7 +143,7 @@ build_gem "bacon", "1.0.0" build_gemspec - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" gem "appraisal", :path => #{PROJECT_ROOT.inspect} @@ -153,7 +153,7 @@ end GEMFILE - build_appraisal_file <<-APPRAISALS.strip_heredoc + build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip appraise "1.0.0" do gem "bacon", "1.0.0" end @@ -162,7 +162,7 @@ run "bundle install --local" run "appraisal generate" - expect(content_of("gemfiles/1.0.0.gemfile")).to eq <<-GEMFILE.strip_heredoc + expect(content_of("gemfiles/1.0.0.gemfile")).to eq <<-GEMFILE.strip_heredoc.rstrip # This file was generated by Appraisal source "https://rubygems.org" diff --git a/spec/acceptance/gemspec_spec.rb b/spec/acceptance/gemspec_spec.rb index 034ec1e4..1db139cc 100644 --- a/spec/acceptance/gemspec_spec.rb +++ b/spec/acceptance/gemspec_spec.rb @@ -9,7 +9,7 @@ it "supports gemspec syntax with default options" do build_gemspec - write_file "Gemfile", <<-GEMFILE.strip_heredoc + write_file "Gemfile", <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" gem 'appraisal', :path => #{PROJECT_ROOT.inspect} @@ -27,7 +27,7 @@ it "supports gemspec syntax with path option" do build_gemspec "specdir" - write_file "Gemfile", <<-GEMFILE.strip_heredoc + write_file "Gemfile", <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" gem 'appraisal', :path => #{PROJECT_ROOT.inspect} @@ -43,7 +43,7 @@ end def build_appraisal_file - appraisals = <<-APPRAISALS.strip_heredoc + appraisals = <<-APPRAISALS.strip_heredoc.rstrip appraise 'stock' do gem 'rake' end @@ -52,7 +52,7 @@ def build_appraisal_file end def build_rakefile - write_file "Rakefile", <<-RAKEFILE.strip_heredoc + write_file "Rakefile", <<-RAKEFILE.strip_heredoc.rstrip require 'rubygems' require 'bundler/setup' require 'appraisal' @@ -71,7 +71,7 @@ def build_gemspec(path = ".") nil end - write_file File.join(path, "gemspec_project.gemspec"), <<-GEMSPEC.strip_heredoc + write_file File.join(path, "gemspec_project.gemspec"), <<-GEMSPEC.strip_heredoc.rstrip Gem::Specification.new do |s| s.name = 'gemspec_project' s.version = '0.1' diff --git a/spec/appraisal/appraisal_spec.rb b/spec/appraisal/appraisal_spec.rb index 545ec8cf..4a694411 100644 --- a/spec/appraisal/appraisal_spec.rb +++ b/spec/appraisal/appraisal_spec.rb @@ -45,7 +45,7 @@ end it "generates a gemfile with multiple lines of custom heading" do - heading = <<-HEADING.strip_heredoc + heading = <<-HEADING.strip_heredoc.rstrip frozen_string_literal: true\n This file was generated with a custom heading! HEADING @@ -56,7 +56,7 @@ appraisal.write_gemfile - expected_output = <<-HEADING.strip_heredoc + expected_output = <<-HEADING.strip_heredoc.rstrip # frozen_string_literal: true\n # This file was generated with a custom heading! HEADING diff --git a/spec/appraisal/customize_spec.rb b/spec/appraisal/customize_spec.rb index d3687a13..d833f8c4 100644 --- a/spec/appraisal/customize_spec.rb +++ b/spec/appraisal/customize_spec.rb @@ -8,7 +8,7 @@ let(:appraisal) { Appraisal::Appraisal.new("test", "Gemfile") } let(:single_line_heading) { "This file was generated with a custom heading!" } let(:multi_line_heading) do - <<-HEADING.strip_heredoc + <<-HEADING.strip_heredoc.rstrip frozen_string_literal: true This file was generated with a custom heading! diff --git a/spec/appraisal/dependency_list_spec.rb b/spec/appraisal/dependency_list_spec.rb index 6d2b4def..a9fac337 100644 --- a/spec/appraisal/dependency_list_spec.rb +++ b/spec/appraisal/dependency_list_spec.rb @@ -17,7 +17,7 @@ dependency_list.add("rails", ["4.1.4"]) dependency_list.add("bundler", ["1.7.2"]) - expect(dependency_list.to_s).to eq <<-GEMS.strip_heredoc + expect(dependency_list.to_s).to eq <<-GEMS.strip_heredoc.rstrip gem "rails", "4.1.4" gem "bundler", "1.7.2" GEMS diff --git a/spec/appraisal/gemfile_spec.rb b/spec/appraisal/gemfile_spec.rb index 51b967ba..d15f815d 100644 --- a/spec/appraisal/gemfile_spec.rb +++ b/spec/appraisal/gemfile_spec.rb @@ -47,7 +47,7 @@ gem "one" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip group :development, :test do gem "one" end @@ -69,7 +69,7 @@ end end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip group :development, :test do git "git://example.com/repo.git" do gem "two" @@ -93,7 +93,7 @@ gem "one" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip platforms :jruby do gem "one" end @@ -115,7 +115,7 @@ end end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip platforms :jruby do git "git://example.com/repo.git" do gem "two" @@ -139,7 +139,7 @@ gem "one" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip git "git://example.com/repo.git" do gem "one" end @@ -161,7 +161,7 @@ end end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip git "git://example.com/repo.git" do path "../.." do gem "three" @@ -185,7 +185,7 @@ gem "one" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip path "../../path" do gem "one" end @@ -195,6 +195,7 @@ it "supports nested DSL within path syntax" do gemfile = described_class.new + # TODO: Small bug: order in a Gemfile can be important for certain gems, but order is not preserved. gemfile.path "../path" do group :development, :test do gem "one" @@ -206,22 +207,22 @@ gem "three" end end - - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + fixture_gemfile = <<-GEMFILE.strip_heredoc.rstrip path "../../path" do git "git://example.com/repo.git" do gem "three" end - + group :development, :test do gem "one" end - + platforms :jruby do gem "two" end end GEMFILE + expect(gemfile.to_s).to eq fixture_gemfile end context "excess new line" do @@ -317,7 +318,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip path "../" do gem "bacon" end @@ -331,7 +332,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip path "../../bacon" do gem "bacon" end @@ -345,7 +346,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip path "/tmp" do gem "bacon" end @@ -361,7 +362,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip git "../" do gem "bacon" end @@ -375,7 +376,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip git "../../bacon" do gem "bacon" end @@ -389,7 +390,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip git "/tmp" do gem "bacon" end @@ -403,7 +404,7 @@ gem "bacon" end - expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc + expect(gemfile.to_s).to eq <<-GEMFILE.strip_heredoc.rstrip git "git@github.com:bacon/bacon.git" do gem "bacon" end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d9313f5c..8eb8a448 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -22,7 +22,6 @@ require "support/acceptance_test_helpers" require "support/stream_helpers" - PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..")).freeze TMP_GEM_ROOT = File.join(PROJECT_ROOT, "tmp", "bundler") TMP_GEM_BUILD = File.join(PROJECT_ROOT, "tmp", "build") diff --git a/spec/support/acceptance_test_helpers.rb b/spec/support/acceptance_test_helpers.rb index 6db7fbc1..c20ba153 100644 --- a/spec/support/acceptance_test_helpers.rb +++ b/spec/support/acceptance_test_helpers.rb @@ -29,6 +29,12 @@ module AcceptanceTestHelpers end end + before :git_local => true do + unless Appraisal::Utils.support_git_local_installation? + pending "This Bundler version does not support sourcing gems from git repos on local filesystem." + end + end + before do cleanup_artifacts save_environment_variables @@ -48,7 +54,7 @@ module AcceptanceTestHelpers # Unfortunately, there is no ENV variable that has access to the "dev" concept directly. # Perhaps the best we can do is parse RUBY_DESCRIPTION? # > RUBY_DESCRIPTION - # "ruby 3.5.0dev (2025-02-20T18:14:37Z master b2cf48f406) +PRISM [arm64-darwin24]" + # "ruby 3.5.0dev (2025-02-20T18:14:37Z ... etc) def ruby_dev_append RUBY_DESCRIPTION.include?("dev") ? "-dev" : "" end @@ -92,7 +98,7 @@ def add_gemspec_to_gemfile end def build_gemspec - write_file "stage.gemspec", <<-GEMSPEC.strip_heredoc + write_file "stage.gemspec", <<-GEMSPEC.strip_heredoc.rstrip Gem::Specification.new do |s| s.name = 'stage' s.version = '0.1' @@ -105,7 +111,7 @@ def build_gemspec def content_of(path) file(path).read.tap do |content| content.gsub!(/(\S+): /, ':\\1 => ') - end + end.strip end def file(path) @@ -142,7 +148,7 @@ def ensure_bundler_is_available return unless $?.exitstatus != 0 - puts <<-WARNING.strip_heredoc + puts <<-WARNING.strip_heredoc.rstrip Reinstall Bundler to #{TMP_GEM_ROOT} as `BUNDLE_DISABLE_SHARED_GEMS` is enabled. WARNING @@ -152,7 +158,7 @@ def ensure_bundler_is_available end def build_default_gemfile - build_gemfile <<-GEMFILE.strip_heredoc + build_gemfile <<-GEMFILE.strip_heredoc.rstrip source 'https://rubygems.org' gem 'appraisal', :path => '#{PROJECT_ROOT}' @@ -180,7 +186,7 @@ def run(command, raise_on_error = true) puts output if ENV["VERBOSE"] if raise_on_error && exitstatus != 0 - raise <<-ERROR_MESSAGE.strip_heredoc + raise <<-ERROR_MESSAGE.strip_heredoc.rstrip Command #{command.inspect} exited with status #{exitstatus}. Output: #{output.gsub(/^/, " ")} ERROR_MESSAGE diff --git a/spec/support/dependency_helpers.rb b/spec/support/dependency_helpers.rb index 6dfbd3a8..c3ff63bc 100644 --- a/spec/support/dependency_helpers.rb +++ b/spec/support/dependency_helpers.rb @@ -1,29 +1,55 @@ # frozen_string_literal: true module DependencyHelpers - def build_gem(gem_name, version = "1.0.0") + DEFAULT_OPTS = { + :skip_build => false, + :skip_install => false, + }.freeze + # @param opts [String, Hash] version string, or options hash + # @option :skip_build [Boolean, nil] skip running gem build, default is false + # @option :skip_install [Boolean, nil] skip running gem install, default is value of skip_build + # @option :version [String, nil] version for the gem, default is "1.0.0" + # @return void + def build_gem(gem_name, opts = {}) ENV["GEM_HOME"] = TMP_GEM_ROOT - + version = "1.0.0" # default + + if opts.respond_to?(:has_key?) + version = opts[:version] if opts.has_key?(:version) + opts[:skip_build] = false unless opts.has_key?(:skip_build) + opts[:skip_install] = opts[:skip_build] unless opts.has_key?(:skip_install) + else + version = case opts + when String then opts + when nil then "1.0.0" + else + raise ArgumentError, "Unexpected value for opts (must be version string or options Hash): #{opts}" + end + opts = DEFAULT_OPTS.dup + end + skip_build = opts[:skip_build] + skip_install = opts[:skip_install] return if File.exist? "#{TMP_GEM_ROOT}/gems/#{gem_name}-#{version}" - FileUtils.mkdir_p "#{TMP_GEM_BUILD}/#{gem_name}/lib" + build_dir = "#{TMP_GEM_BUILD}/#{gem_name}" + FileUtils.mkdir_p "#{build_dir}/lib" - FileUtils.cd "#{TMP_GEM_BUILD}/#{gem_name}" do + FileUtils.cd build_dir do gemspec = "#{gem_name}.gemspec" lib_file = "lib/#{gem_name}.rb" File.open gemspec, "w" do |file| - file.puts <<-GEMSPEC.strip_heredoc - Gem::Specification.new do |s| - s.name = #{gem_name.inspect} - s.version = #{version.inspect} - s.authors = 'Mr. Smith' - s.summary = 'summary' - s.files = #{lib_file.inspect} - s.license = 'MIT' - s.homepage = 'http://github.com/thoughtbot/#{gem_name}' - s.required_ruby_version = '>= 2.3.0' - end + file.puts <<-GEMSPEC.strip_heredoc.rstrip + Gem::Specification.new do |s| + s.name = #{gem_name.inspect} + s.version = #{version.inspect} + s.authors = 'Mr. Smith' + s.summary = 'summary' + s.files = #{lib_file.inspect} + s.license = 'MIT' + s.homepage = 'http://github.com/thoughtbot/#{gem_name}' + s.required_ruby_version = '>= 1.8.7' + end GEMSPEC end @@ -33,14 +59,23 @@ def build_gem(gem_name, version = "1.0.0") redirect = ENV["VERBOSE"] ? "" : "2>&1" - puts "building gem: #{gem_name} #{version}" if ENV["VERBOSE"] - %x(gem build #{gemspec} #{redirect}) + # Caller may turn it into a git repo here + yield build_dir, redirect if block_given? - puts "installing gem: #{gem_name} #{version}" if ENV["VERBOSE"] - %x(gem install -lN #{gem_name}-#{version}.gem -v #{version} #{redirect}) + unless skip_build + puts "building gem: #{gem_name} #{version}" if ENV["VERBOSE"] + %x(gem build #{gemspec} #{redirect}) + end + + unless skip_install + puts "installing gem: #{gem_name} #{version}" if ENV["VERBOSE"] + %x(gem install -lN #{gem_name}-#{version}.gem -v #{version} #{redirect}) + end puts "" if ENV["VERBOSE"] end + + nil end def build_gems(gems) @@ -48,23 +83,24 @@ def build_gems(gems) end def build_git_gem(gem_name, version = "1.0.0") - puts "building git gem: #{gem_name} #{version}" if ENV["VERBOSE"] - build_gem gem_name, version - - Dir.chdir "#{TMP_GEM_BUILD}/#{gem_name}" do - %x(git init . --initial-branch=master) - %x(git config user.email "appraisal@thoughtbot.com") - %x(git config user.name "Appraisal") - %x(git config commit.gpgsign false) - %x(git add .) - %x(git commit --all --no-verify --message "initial commit") + build_gem(gem_name, {:version => version, :skip_build => true, :skip_install => true}) do |_gem_dir, redirect| + # At this point we have a gem file structure on disk inside `_gem_dir`. + # Since we are already inside _gem_dir, we do not need to chdir. + puts "initializing git repo for gem: #{gem_name} #{version}" if ENV["VERBOSE"] + # Set up our clone of the bare git repository, and push our gem into it + %x(git init . --initial-branch=main #{redirect}) + %x(git config user.email "appraisal@thoughtbot.com" #{redirect}) + %x(git config user.name "Appraisal" #{redirect}) + %x(git config commit.gpgsign false #{redirect}) + %x(git add . #{redirect}) + %x(git commit --all --no-verify --message "initial commit" #{redirect}) end # Cleanup Bundler cache path manually for now git_cache_path = File.join(ENV["GEM_HOME"], "cache", "bundler", "git") Dir[File.join(git_cache_path, "#{gem_name}-*")].each do |path| - puts "deleting: #{path}" if ENV["VERBOSE"] + puts "cleaning up bundler git cache: #{path}" if ENV["VERBOSE"] FileUtils.rm_r(path) end end From 4ec2725663185ca7c70f956a17b3e401300a283a Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Fri, 21 Feb 2025 18:21:25 +0700 Subject: [PATCH 09/60] =?UTF-8?q?=F0=9F=91=B7=20add=20Ruby=203.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f6743f86..6cbf79e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,6 +17,7 @@ jobs: fail-fast: false matrix: ruby: + - '3.4' - '3.3' - '3.2' - '3.1' From 594690df38ab344c0ab0e6eb6ef1c36e03f578dd Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 01:41:17 +0700 Subject: [PATCH 10/60] =?UTF-8?q?=F0=9F=90=9B=20Fix=20inconsistent=20inden?= =?UTF-8?q?tation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tool-versions | 1 + lib/appraisal/bundler_dsl.rb | 15 +++++++++------ spec/appraisal/gemfile_spec.rb | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.tool-versions b/.tool-versions index 973bb631..0e646452 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1,2 @@ `ruby 3.4.2 +ruby 3.3.7 diff --git a/lib/appraisal/bundler_dsl.rb b/lib/appraisal/bundler_dsl.rb index 1419e8ca..0881c4a7 100644 --- a/lib/appraisal/bundler_dsl.rb +++ b/lib/appraisal/bundler_dsl.rb @@ -165,12 +165,15 @@ def indent(string) indent_by = ENV.fetch("APPRAISAL_INDENTER", "lookahead") if indent_by == "lookahead" # Default indenter for Appraisal v3 - # Uses a look-ahead to indent lines that start with a "word" (as defined by RegExp) - # (optionally preceded by whitespace). - # First it finds the point where the white space ends / words starts, - # and inserts two spaces at that point, leaving any existing whitespace in place. - # In other words, retain existing indentation, and indent the line again. - string.gsub(/^(?=(\s*)\w)/, " ").rstrip + # Uses a look-behind to indent lines are more than just empty space. + # In other words, retain existing indentation, and indent the line again, but not on empty lines. + string. + # NOTES: + # (?![\r\n]) - Negative Look Behind which requires that the following pattern, + # which is (\s*) in this case, *not* be followed by a new line character + # (\s*) - Captures whitespace at beginning of the line + gsub(/^(?![\r\n])(\s*)/, ' \0'). + rstrip elsif indent_by == "capture" # Original indentation regex for Appraisal < v3 string.gsub(/^(.+)$/, ' \1').rstrip diff --git a/spec/appraisal/gemfile_spec.rb b/spec/appraisal/gemfile_spec.rb index d15f815d..07c02f6f 100644 --- a/spec/appraisal/gemfile_spec.rb +++ b/spec/appraisal/gemfile_spec.rb @@ -212,11 +212,11 @@ git "git://example.com/repo.git" do gem "three" end - + group :development, :test do gem "one" end - + platforms :jruby do gem "two" end From 386ddb679796ababc317356ddb5ff1d64ff4c83f Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 01:42:33 +0700 Subject: [PATCH 11/60] =?UTF-8?q?=F0=9F=93=9D=20Documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/appraisal/bundler_dsl.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/appraisal/bundler_dsl.rb b/lib/appraisal/bundler_dsl.rb index 0881c4a7..e39d0356 100644 --- a/lib/appraisal/bundler_dsl.rb +++ b/lib/appraisal/bundler_dsl.rb @@ -172,6 +172,7 @@ def indent(string) # (?![\r\n]) - Negative Look Behind which requires that the following pattern, # which is (\s*) in this case, *not* be followed by a new line character # (\s*) - Captures whitespace at beginning of the line + # Learn more here: https://learnbyexample.github.io/Ruby_Regexp/lookarounds.html gsub(/^(?![\r\n])(\s*)/, ' \0'). rstrip elsif indent_by == "capture" From 7a2ec8e62b5d0bfd66161dd0e48f4d9c8a3eed5e Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 01:49:49 +0700 Subject: [PATCH 12/60] =?UTF-8?q?=F0=9F=92=9A=20Fix=20inconsistent=20inden?= =?UTF-8?q?tation=20in=20spec=20fixtures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tool-versions | 3 +-- .../appraisals_file_bundler_dsl_compatibility_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.tool-versions b/.tool-versions index 0e646452..ae5ecdb2 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1 @@ -`ruby 3.4.2 -ruby 3.3.7 +ruby 3.4.2 diff --git a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb index 7112c55c..084b9984 100644 --- a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb +++ b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb @@ -130,7 +130,7 @@ gem "orange_juice" gem "omelette", :git => "../../build/omelette" gem "bacon" - + platforms :rbx do gem "ham" end @@ -139,7 +139,7 @@ platforms :ruby, :jruby do gem "milk" gem "yoghurt" - + group :lunch do gem "coffee" end From f7225612a64adb3fb9d55c49d665db9d37add98f Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 01:53:46 +0700 Subject: [PATCH 13/60] =?UTF-8?q?=F0=9F=9A=A8=20Lint=20lock=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .rubocop_gradual.lock | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 9629a5ec..0ea364bf 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -18,14 +18,15 @@ [17, 5, 62, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 4082816720], [21, 5, 516, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2780620929] ], - "lib/appraisal/utils.rb:3242656341": [ + "lib/appraisal/utils.rb:3706894031": [ [6, 5, 129, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 733338411], - [13, 5, 354, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 119295155], - [35, 5, 152, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1306460482], - [42, 5, 151, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1120325158], - [48, 5, 98, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 714993131], - [52, 5, 244, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1461524090], - [61, 5, 111, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1909626476] + [10, 5, 124, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 222857520], + [17, 5, 354, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 119295155], + [39, 5, 152, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1306460482], + [46, 5, 151, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1120325158], + [52, 5, 98, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 714993131], + [56, 5, 244, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1461524090], + [65, 5, 111, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1909626476] ], "spec/acceptance/cli/clean_spec.rb:1564995421": [ [3, 23, 17, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 1606893221] @@ -36,7 +37,7 @@ "spec/acceptance/cli/help_spec.rb:3569358941": [ [3, 23, 16, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 2148351217] ], - "spec/acceptance/cli/install_spec.rb:1306756550": [ + "spec/acceptance/cli/install_spec.rb:3249736824": [ [3, 23, 19, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3284642881] ], "spec/acceptance/cli/list_spec.rb:36921834": [ @@ -86,7 +87,7 @@ [68, 7, 85, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 66, 67].", 3874694796], [72, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] ], - "spec/appraisal/gemfile_spec.rb:2644921119": [ + "spec/appraisal/gemfile_spec.rb:3969538335": [ [228, 11, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3608128140], [229, 13, 13, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 420381022], [236, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3511037132], @@ -102,8 +103,8 @@ "spec/appraisal/utils_spec.rb:2286225770": [ [62, 17, 58, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 1573223692] ], - "spec/support/acceptance_test_helpers.rb:293636491": [ - [143, 5, 32, "Style/InvertibleUnlessCondition: Prefer `if $?.exitstatus == 0` over `unless $?.exitstatus != 0`.", 4187517264] + "spec/support/acceptance_test_helpers.rb:3072478660": [ + [149, 5, 32, "Style/InvertibleUnlessCondition: Prefer `if $?.exitstatus == 0` over `unless $?.exitstatus != 0`.", 4187517264] ], "spec/support/stream_helpers.rb:3654818709": [ [10, 17, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] From 12002dac9760519072a17b3f9c2df213286fb98b Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 01:54:47 +0700 Subject: [PATCH 14/60] =?UTF-8?q?=F0=9F=91=B7=20Add=20Ruby=202.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6cbf79e8..17c5d310 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,6 +23,7 @@ jobs: - '3.1' - '3.0' - '2.7' + - '2.6' - 'head' - jruby - jruby-head From df71fbbc79904e6d19c36c1dba87cc212fdd6b14 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 05:12:09 +0700 Subject: [PATCH 15/60] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Lookahead=20!=3D=20L?= =?UTF-8?q?ookbehind?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/appraisal/bundler_dsl.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/appraisal/bundler_dsl.rb b/lib/appraisal/bundler_dsl.rb index e39d0356..f0c38ef5 100644 --- a/lib/appraisal/bundler_dsl.rb +++ b/lib/appraisal/bundler_dsl.rb @@ -162,10 +162,10 @@ def #{method_name}_entry_for_dup end def indent(string) - indent_by = ENV.fetch("APPRAISAL_INDENTER", "lookahead") - if indent_by == "lookahead" + indent_by = ENV.fetch("APPRAISAL_INDENTER", "lookaround") + if indent_by == "lookaround" # Default indenter for Appraisal v3 - # Uses a look-behind to indent lines are more than just empty space. + # Uses a "look-around" of the "look-behind" variety to indent lines are more than just empty space. # In other words, retain existing indentation, and indent the line again, but not on empty lines. string. # NOTES: From 5fcfb4352ed8e53f66986c697230fd18e9dd6db3 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 05:22:17 +0700 Subject: [PATCH 16/60] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Fix=20typo=20in=20do?= =?UTF-8?q?cumentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/appraisal/bundler_dsl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/appraisal/bundler_dsl.rb b/lib/appraisal/bundler_dsl.rb index f0c38ef5..cf52d422 100644 --- a/lib/appraisal/bundler_dsl.rb +++ b/lib/appraisal/bundler_dsl.rb @@ -165,7 +165,7 @@ def indent(string) indent_by = ENV.fetch("APPRAISAL_INDENTER", "lookaround") if indent_by == "lookaround" # Default indenter for Appraisal v3 - # Uses a "look-around" of the "look-behind" variety to indent lines are more than just empty space. + # Uses a "look-around" of the "look-behind" variety to indent lines that are more than just empty space. # In other words, retain existing indentation, and indent the line again, but not on empty lines. string. # NOTES: From 975ded0af5ff67b984393166290b34d64b322d72 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 05:23:38 +0700 Subject: [PATCH 17/60] =?UTF-8?q?=F0=9F=91=B7=20Remove=20Ruby=202.6=20from?= =?UTF-8?q?=20CI=20(to=20be=20added=20back=20in=20another=20PR)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 17c5d310..6cbf79e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,7 +23,6 @@ jobs: - '3.1' - '3.0' - '2.7' - - '2.6' - 'head' - jruby - jruby-head From 774054cb4528f2ac2bfbc8bbc30d3f60c3edcbb1 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Sat, 22 Feb 2025 05:39:34 +0700 Subject: [PATCH 18/60] =?UTF-8?q?=E2=9C=A8=20Support=20eval=5Fgemfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixes #154 --- README.md | 84 ++++++++++++++++++++++++++++ lib/appraisal/appraisal.rb | 4 ++ lib/appraisal/bundler_dsl.rb | 12 ++++ spec/acceptance/eval_gemfile_spec.rb | 81 +++++++++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 spec/acceptance/eval_gemfile_spec.rb diff --git a/README.md b/README.md index aa2cfda0..2b8da76b 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,90 @@ When you prefix a command with `appraisal`, the command is run with the appropriate Gemfile for that appraisal, ensuring the correct dependencies are used. +Sharing Modular Gemfiles between Appraisals +------- + +_New for version 3.0_ + +It is common for Appraisals to duplicate sets of gems, and sometimes it +makes sense to DRY this up into a shared, modular, gemfile. +In a scenario where you do not load your main Gemfile in your Appraisals, +but you want to declare your various gem sets for e.g. +`%w(coverage test documentation audit)` once each, you can re-use the same +modular gemfiles for local development by referencing them from the main +Gemfile. + +To do this, use the `eval_gemfile` declaration within the necessary +`appraise` block in your `Appraisals` file, which will behave the same as +`eval_gemfile` does in a normal Gemfile. + +### Example Usage + +You could put your modular gemfiles in the `gemfiles` directory, or nest +them in `gemfiles/modular/*`, which will be used for this example. + +**Gemfile** +```ruby +eval_gemfile "gemfiles/modular/audit.gemfile" +``` + +**gemfiles/modular/audit.gemfile** +```ruby +# Many gems are dropping support for Ruby < 3.1, +# so we only want to run our security audit in CI on Ruby 3.1+ +gem "bundler-audit", "~> 0.9.2" +# And other security audit gems... +``` + +**Appraisals** +```ruby +appraise "ruby-2-7" do + gem "dummy" +end + +appraise "ruby-3-0" do + gem "dummy" +end + +appraise "ruby-3-1" do + gem "dummy" + eval_gemfile "modular/audit.gemfile" +end + +appraise "ruby-3-2" do + gem "dummy" + eval_gemfile "modular/audit.gemfile" +end + +appraise "ruby-3-3" do + gem "dummy" + eval_gemfile "modular/audit.gemfile" +end + +appraise "ruby-3-4" do + gem "dummy" + eval_gemfile "modular/audit.gemfile" +end +``` + +**Appraisal.root.gemfile** +```ruby +source "https://rubygems.org" + +# Appraisal Root Gemfile is for running appraisal to generate the Appraisal Gemfiles +# We do not load the standard Gemfile, as it is tailored for local development, +# while appraisals are tailored for CI. + +gemspec + +gem "appraisal" +``` + +Now when you need to update your appraisals: +```shell +BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal update +``` + Removing Gems using Appraisal ------- diff --git a/lib/appraisal/appraisal.rb b/lib/appraisal/appraisal.rb index 3d76c5a4..ccbed470 100644 --- a/lib/appraisal/appraisal.rb +++ b/lib/appraisal/appraisal.rb @@ -19,6 +19,10 @@ def initialize(name, source_gemfile) @gemfile = source_gemfile.dup end + def eval_gemfile(*args) + gemfile.eval_gemfile(*args) + end + def gem(*args) gemfile.gem(*args) end diff --git a/lib/appraisal/bundler_dsl.rb b/lib/appraisal/bundler_dsl.rb index cf52d422..4e1a4a06 100644 --- a/lib/appraisal/bundler_dsl.rb +++ b/lib/appraisal/bundler_dsl.rb @@ -18,6 +18,7 @@ class BundlerDSL source_blocks install_if gemspec + eval_gemfile ] def initialize @@ -32,12 +33,17 @@ def initialize @source_blocks = OrderedHash.new @git_sources = {} @install_if = {} + @eval_gemfile = [] end def run(&block) instance_exec(&block) end + def eval_gemfile(path, contents = nil) + @eval_gemfile << [path, contents] + end + def gem(name, *requirements) @dependencies.add(name, substitute_git_source(requirements)) end @@ -114,6 +120,12 @@ def git_source(source, &block) private + def eval_gemfile_entry + @eval_gemfile.map { |(p, c)| "eval_gemfile(#{p.inspect}#{", #{c.inspect}" if c})" } * "\n\n" + end + + alias_method :eval_gemfile_entry_for_dup, :eval_gemfile_entry + def source_entry @sources.uniq.map { |source| "source #{source.inspect}" }.join("\n") end diff --git a/spec/acceptance/eval_gemfile_spec.rb b/spec/acceptance/eval_gemfile_spec.rb new file mode 100644 index 00000000..7ea54c6d --- /dev/null +++ b/spec/acceptance/eval_gemfile_spec.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "eval_gemfile" do + before do + build_appraisal_file + build_modular_gemfile + build_rakefile + build_gemspec + end + + it "supports eval_gemfile syntax" do + write_file "Gemfile", <<-GEMFILE + source "https://rubygems.org" + + gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + + gemspec + GEMFILE + + run "bundle install --local" + run "appraisal install" + output = run "appraisal rake version" + + expect(output).to include "Loaded 1.1.0" + end + + def build_modular_gemfile + begin + Dir.mkdir("tmp/stage/gemfiles") + rescue + nil + end + + write_file File.join("gemfiles", "im_with_dummy"), <<-GEMFILE + # No source needed because this is a modular gemfile intended to be loaded into another gemfile, + # which will define source. + gem 'dummy' + GEMFILE + end + + def build_appraisal_file + super(<<-APPRAISALS) + appraise 'stock' do + gem 'rake' + eval_gemfile "im_with_dummy" + end + APPRAISALS + end + + def build_rakefile + write_file "Rakefile", <<-RAKEFILE + require 'rubygems' + require 'bundler/setup' + require 'appraisal' + + task :version do + require 'dummy' + puts "Loaded \#{$dummy_version}" + end + RAKEFILE + end + + def build_gemspec(path = ".") + begin + Dir.mkdir("tmp/stage/#{path}") + rescue + nil + end + + write_file File.join(path, "gemspec_project.gemspec"), <<-GEMSPEC + Gem::Specification.new do |s| + s.name = 'gemspec_project' + s.version = '0.1' + s.summary = 'Awesome Gem!' + s.authors = "Appraisal" + end + GEMSPEC + end +end From 46d71e67e523e8add8d8e55e879df89aaa1927c9 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Mon, 3 Feb 2025 22:12:21 +0700 Subject: [PATCH 19/60] =?UTF-8?q?=F0=9F=93=9D=20Documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index d90a1616..eecd1d1c 100644 --- a/Gemfile +++ b/Gemfile @@ -6,7 +6,7 @@ gemspec ruby_version = Gem::Version.new(RUBY_VERSION) platform :mri do - # Debugging + # Debugging - Ensure ENV["DEBUG"] == "true" to use debuggers within spec suite if ruby_version < Gem::Version.new("2.7") # Use byebug in code gem "byebug", ">= 11" From c07c0c9e336e277d6a5d2e16cac7bc518319d74c Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Tue, 25 Feb 2025 00:13:38 +0700 Subject: [PATCH 20/60] =?UTF-8?q?=F0=9F=90=9B=20Ruby=201.8=20compat:=20Rep?= =?UTF-8?q?lace=20=5F=5Fdir=5F=5F=20with=20File.dirname(=5F=5FFILE=5F=5F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ .rubocop_gradual.lock | 8 ++------ .tool-versions | 2 +- appraisal.gemspec | 11 ++++++----- bin/bundle | 2 +- bin/rspec | 4 ++-- spec/acceptance/bundle_without_spec.rb | 2 +- 7 files changed, 15 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index acc12f06..46fa9b6b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ pkg Gemfile.lock .bundle .DS_Store + +spec/tmp diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 0ea364bf..4b32d2d7 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -1,5 +1,5 @@ { - "Gemfile:2720967286": [ + "Gemfile:3872962921": [ [26, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], [28, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], [30, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] @@ -294,11 +294,7 @@ [40, 36, 2, "Style/AndOr: Use `||` instead of `or`.", 5861240] ], "spec/tmp/bundler/gems/rake-13.2.1/rake.gemspec:2780653655": [ - [12, 19, 2, "Lint/Syntax: unexpected token tLSHFT\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5859461], - [13, 25, 7, "Lint/Syntax: unexpected token tIDENTIFIER\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 1804902097], - [14, 15, 2, "Lint/Syntax: unexpected token kIN\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5861154], - [16, 7, 1, "Lint/Syntax: unexpected token tSTAR\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177551], - [16, 24, 1, "Lint/Syntax: unterminated string meets end of file\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177538] + [12, 19, 2, "Lint/Syntax: unexpected token tLSHFT\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5859461] ], "spec/tmp/bundler/gems/rotten_egg-1.0.0/lib/rotten_egg.rb:2010666510": [ [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 2573678312] diff --git a/.tool-versions b/.tool-versions index ae5ecdb2..aba173c5 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 3.4.2 +ruby truffleruby-24.1.2 diff --git a/appraisal.gemspec b/appraisal.gemspec index 6a037762..67da5627 100644 --- a/appraisal.gemspec +++ b/appraisal.gemspec @@ -3,7 +3,8 @@ # TODO: Switch to require_relative once support for Ruby < 2 is dropped. # require_relative "lib/appraisal/version" -$:.push(File.expand_path("lib", __dir__)) +lib = File.expand_path("../lib", __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "appraisal/version" Gem::Specification.new do |s| @@ -42,10 +43,10 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 1.8.7" - s.add_runtime_dependency("bundler", ">= 1.17.3") # Last version supporting Ruby 1.8.7 - s.add_runtime_dependency("rake", ">= 10") # Last version supporting Ruby 1.8.7 - s.add_runtime_dependency("thor", ">= 0.14.0") + s.add_runtime_dependency("bundler", ">= 1.17.3") # Last version supporting Ruby 1.8.7 + s.add_runtime_dependency("rake", ">= 10") # Last version supporting Ruby 1.8.7 + s.add_runtime_dependency("thor", ">= 0.14") # Last version supporting Ruby 1.8.7 && Rails 3 s.add_development_dependency("activesupport", ">= 3.2.21") - s.add_development_dependency("rspec", "~> 3.0") + s.add_development_dependency("rspec", "~> 3.13") end diff --git a/bin/bundle b/bin/bundle index 8f20a586..fcf376ea 100755 --- a/bin/bundle +++ b/bin/bundle @@ -41,7 +41,7 @@ m = Module.new do gemfile = ENV["BUNDLE_GEMFILE"] return gemfile if gemfile && !gemfile.empty? - File.expand_path("../Gemfile", __dir__) + File.expand_path("../Gemfile", File.dirname(__FILE__)) end def lockfile diff --git a/bin/rspec b/bin/rspec index cb53ebe5..d6b5fc6e 100755 --- a/bin/rspec +++ b/bin/rspec @@ -8,9 +8,9 @@ # this file is here to facilitate running it. # -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", File.dirname(__FILE__)) -bundle_binstub = File.expand_path("bundle", __dir__) +bundle_binstub = File.expand_path("bundle", File.dirname(__FILE__)) if File.file?(bundle_binstub) if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index fbe5ad31..4194071e 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "Bundle without group" do it "config set --local without group is honored by Bundler" do - pending "config set --local without group support seems broken, see: https://github.com/rubygems/rubygems/issues/8518" + # pending "config set --local without group support seems broken, see: https://github.com/rubygems/rubygems/issues/8518" build_gems %w[pancake orange_juice waffle coffee sausage soda] build_gemfile <<-GEMFILE.strip_heredoc.rstrip From 1ceb8ab5eac363b905c5026dbba5d9145a031590 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Tue, 25 Feb 2025 00:17:23 +0700 Subject: [PATCH 21/60] =?UTF-8?q?=F0=9F=9A=A8=20Lint=20lock=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .rubocop_gradual.lock | 364 +----------------------------------------- 1 file changed, 1 insertion(+), 363 deletions(-) diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 4b32d2d7..fc654a0e 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -4,7 +4,7 @@ [28, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], [30, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] ], - "bin/bundle:3123891436": [ + "bin/bundle:41466308": [ [66, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] ], "lib/appraisal/appraisal_file.rb:3486777149": [ @@ -108,367 +108,5 @@ ], "spec/support/stream_helpers.rb:3654818709": [ [10, 17, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] - ], - "spec/tmp/build/bagel/lib/bagel.rb:817034159": [ - [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 93522089] - ], - "spec/tmp/build/coffee/lib/coffee.rb:3015295950": [ - [1, 1, 15, "Style/GlobalVars: Do not introduce global variables.", 1715453096] - ], - "spec/tmp/build/croissant/lib/croissant.rb:4104237646": [ - [1, 1, 18, "Style/GlobalVars: Do not introduce global variables.", 2226371368] - ], - "spec/tmp/build/dummy/lib/dummy.rb:1807990539": [ - [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 2877655148] - ], - "spec/tmp/build/egg/lib/egg.rb:3130854087": [ - [1, 1, 12, "Style/GlobalVars: Do not introduce global variables.", 4028848065] - ], - "spec/tmp/build/ham/lib/ham.rb:557050406": [ - [1, 1, 12, "Style/GlobalVars: Do not introduce global variables.", 1287500928] - ], - "spec/tmp/build/mayonnaise/lib/mayonnaise.rb:604109062": [ - [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 3499390688] - ], - "spec/tmp/build/milk/lib/milk.rb:2694353217": [ - [1, 1, 13, "Style/GlobalVars: Do not introduce global variables.", 3069591303] - ], - "spec/tmp/build/omelette/lib/omelette.rb:3378185993": [ - [1, 1, 17, "Style/GlobalVars: Do not introduce global variables.", 576262095] - ], - "spec/tmp/build/orange_juice/lib/orange_juice.rb:3578149981": [ - [1, 1, 21, "Style/GlobalVars: Do not introduce global variables.", 1923934619] - ], - "spec/tmp/build/pain_au_chocolat/lib/pain_au_chocolat.rb:2551039889": [ - [1, 1, 25, "Style/GlobalVars: Do not introduce global variables.", 2391071575] - ], - "spec/tmp/build/pancake/lib/pancake.rb:284512849": [ - [1, 1, 16, "Style/GlobalVars: Do not introduce global variables.", 451124759] - ], - "spec/tmp/build/rotten_egg/lib/rotten_egg.rb:2010666510": [ - [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 2573678312] - ], - "spec/tmp/build/sausage/lib/sausage.rb:1728262677": [ - [1, 1, 16, "Style/GlobalVars: Do not introduce global variables.", 619820115] - ], - "spec/tmp/build/soda/lib/soda.rb:1990629979": [ - [1, 1, 13, "Style/GlobalVars: Do not introduce global variables.", 198441437] - ], - "spec/tmp/build/waffle/lib/waffle.rb:2896717917": [ - [1, 1, 15, "Style/GlobalVars: Do not introduce global variables.", 2356319643] - ], - "spec/tmp/bundler/bin/appraisal:662174372": [ - [18, 10, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] - ], - "spec/tmp/bundler/bin/rake:3146010916": [ - [18, 10, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] - ], - "spec/tmp/bundler/bin/thor:4227855012": [ - [18, 10, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] - ], - "spec/tmp/bundler/gems/bagel-1.0.0/lib/bagel.rb:817034159": [ - [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 93522089] - ], - "spec/tmp/bundler/gems/coffee-1.0.0/lib/coffee.rb:3015295950": [ - [1, 1, 15, "Style/GlobalVars: Do not introduce global variables.", 1715453096] - ], - "spec/tmp/bundler/gems/dummy-1.0.0/lib/dummy.rb:1804502538": [ - [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 2877655148] - ], - "spec/tmp/bundler/gems/dummy-1.1.0/lib/dummy.rb:1807990539": [ - [1, 1, 14, "Style/GlobalVars: Do not introduce global variables.", 2877655148] - ], - "spec/tmp/bundler/gems/ham-1.0.0/lib/ham.rb:557050406": [ - [1, 1, 12, "Style/GlobalVars: Do not introduce global variables.", 1287500928] - ], - "spec/tmp/bundler/gems/mayonnaise-1.0.0/lib/mayonnaise.rb:604109062": [ - [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 3499390688] - ], - "spec/tmp/bundler/gems/milk-1.0.0/lib/milk.rb:2694353217": [ - [1, 1, 13, "Style/GlobalVars: Do not introduce global variables.", 3069591303] - ], - "spec/tmp/bundler/gems/orange_juice-1.0.0/lib/orange_juice.rb:3578149981": [ - [1, 1, 21, "Style/GlobalVars: Do not introduce global variables.", 1923934619] - ], - "spec/tmp/bundler/gems/pancake-1.0.0/lib/pancake.rb:284512849": [ - [1, 1, 16, "Style/GlobalVars: Do not introduce global variables.", 451124759] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake.rb:3015112320": [ - [64, 1, 6, "Style/GlobalVars: Do not introduce global variables.", 3075757472] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/application.rb:3305321773": [ - [63, 21, 6, "Style/GlobalStdStream: Use `$stdout` instead of `STDOUT`.", 3356722952], - [113, 13, 6, "Style/GlobalStdStream: Use `$stderr` instead of `STDERR`.", 3356712163], - [222, 11, 5, "Lint/Loop: Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`).", 191284826], - [236, 5, 122, "Lint/RescueException: Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?", 3552754902], - [305, 65, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [306, 50, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [514, 15, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [523, 20, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [530, 40, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [532, 30, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [537, 78, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [553, 40, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [608, 59, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [638, 54, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [647, 66, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [656, 53, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [664, 60, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [671, 62, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [672, 46, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [681, 71, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [798, 24, 2, "Style/AndOr: Use `||` instead of `or`.", 5861240], - [889, 16, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560], - [895, 20, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560], - [895, 33, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/backtrace.rb:2947413644": [ - [16, 43, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806], - [20, 5, 182, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 684235907] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/clean.rb:597197225": [ - [47, 18, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/cpu_counter.rb:114869078": [ - [7, 5, 51, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1633217579] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/ext/core.rb:37720573": [ - [21, 71, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/file_utils.rb:1092133475": [ - [67, 68, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/file_utils_ext.rb:1080867503": [ - [15, 7, 42, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 598600538] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/invocation_chain.rb:2990720762": [ - [27, 5, 73, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 669377266] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/linked_list.rb:3208307164": [ - [59, 5, 439, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3263738083], - [73, 5, 55, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2265797213], - [78, 5, 40, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 201197260], - [105, 7, 68, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1829672226], - [106, 9, 7, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1309332345] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/private_reader.rb:670493723": [ - [6, 5, 63, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2901108034] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/promise.rb:910582": [ - [65, 7, 40, "Lint/RescueException: Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?", 3824424681] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/rake_module.rb:4177774778": [ - [9, 7, 12, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 4135892607], - [13, 5, 24, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 2330715366], - [16, 7, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2063727135], - [17, 7, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2063727135] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/task.rb:825529577": [ - [220, 9, 116, "Lint/RescueException: Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?", 3582047834], - [278, 15, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560], - [278, 40, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806], - [373, 5, 137, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2016900957] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/task_arguments.rb:2422589739": [ - [66, 5, 63, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 2216682504] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/task_manager.rb:988246897": [ - [27, 31, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806], - [136, 9, 18, "Style/IdenticalConditionalBranches: Move `deps = value || []` out of the conditional.", 3582664887], - [140, 9, 18, "Style/IdenticalConditionalBranches: Move `deps = value || []` out of the conditional.", 3582664887], - [278, 22, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560], - [326, 7, 35, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 402700679] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/testtask.rb:431563537": [ - [112, 48, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [121, 51, 2, "Style/AndOr: Use `||` instead of `or`.", 5861240] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/thread_pool.rb:12277952": [ - [48, 9, 530, "Lint/RescueException: Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`?", 228964421], - [51, 65, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [53, 70, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [116, 9, 48, "Style/InvertibleUnlessCondition: Prefer `if @threads.count >= @max_active_threads` over `unless @threads.count < @max_active_threads`.", 2403143961], - [118, 13, 10, "ThreadSafety/NewThread: Avoid starting new threads.", 3411682361] - ], - "spec/tmp/bundler/gems/rake-13.2.1/lib/rake/win32.rb:4149036273": [ - [40, 36, 2, "Style/AndOr: Use `||` instead of `or`.", 5861240] - ], - "spec/tmp/bundler/gems/rake-13.2.1/rake.gemspec:2780653655": [ - [12, 19, 2, "Lint/Syntax: unexpected token tLSHFT\n(Using Ruby 2.0 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5859461] - ], - "spec/tmp/bundler/gems/rotten_egg-1.0.0/lib/rotten_egg.rb:2010666510": [ - [1, 1, 19, "Style/GlobalVars: Do not introduce global variables.", 2573678312] - ], - "spec/tmp/bundler/gems/sausage-1.0.0/lib/sausage.rb:1728262677": [ - [1, 1, 16, "Style/GlobalVars: Do not introduce global variables.", 619820115] - ], - "spec/tmp/bundler/gems/soda-1.0.0/lib/soda.rb:1990629979": [ - [1, 1, 13, "Style/GlobalVars: Do not introduce global variables.", 198441437] - ], - "spec/tmp/bundler/gems/thor-1.3.2/bin/thor:1678810035": [ - [5, 1, 12, "Style/GlobalVars: Do not introduce global variables.", 2230010895] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor.rb:333295015": [ - [4, 3, 12, "Style/GlobalVars: Do not introduce global variables.", 2230010895], - [13, 7, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 551240135], - [23, 9, 16, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 580261046], - [25, 9, 16, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 580261046], - [39, 9, 32, "Style/IdenticalConditionalBranches: Move `desc usage, description, options` out of the conditional.", 4209929479], - [42, 9, 32, "Style/IdenticalConditionalBranches: Move `desc usage, description, options` out of the conditional.", 4209929479], - [60, 9, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], - [61, 9, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], - [62, 9, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213880165], - [83, 9, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2420967073], - [84, 9, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1012447818], - [102, 7, 4, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2088878297], - [112, 33, 4, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2088878297], - [114, 13, 4, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2088878297], - [119, 7, 4, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2088878297], - [130, 7, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797], - [131, 30, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797], - [132, 7, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797], - [303, 19, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 551240135], - [303, 37, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 551240135], - [304, 22, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 551240135], - [329, 7, 12, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3952225397], - [334, 7, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2063673473], - [359, 7, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], - [362, 11, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], - [364, 11, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], - [367, 7, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], - [429, 7, 23, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 288545224], - [443, 7, 23, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2342089118], - [458, 7, 60, "Performance/InefficientHashSearch: Use `#key?` instead of `#keys.include?`.", 675081132], - [469, 7, 30, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 747165948], - [478, 7, 33, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2836932844], - [482, 7, 23, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 288545224], - [487, 7, 23, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2342089118], - [555, 37, 12, "Style/GlobalVars: Do not introduce global variables.", 2230010895], - [569, 7, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], - [570, 7, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], - [571, 7, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2420967073], - [572, 7, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1012447818], - [573, 7, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213880165], - [575, 10, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], - [575, 20, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], - [576, 22, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213880165], - [581, 47, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], - [581, 54, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2420967073], - [581, 66, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1012447818], - [581, 83, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], - [582, 9, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2759591200], - [582, 17, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], - [582, 24, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2420967073], - [582, 36, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1012447818], - [582, 53, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797], - [582, 70, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213880165], - [583, 9, 30, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 747165948], - [583, 41, 33, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2836932844], - [598, 7, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1888203797] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/actions.rb:1169132954": [ - [12, 5, 84, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3488611255], - [23, 9, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3359610630], - [28, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3225348734], - [29, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3225348734], - [238, 13, 4, "Security/Open: The use of `URI.open` is a serious security risk.", 2087926481] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/base.rb:1396078371": [ - [42, 50, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [143, 9, 11, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3739410329], - [152, 9, 15, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 510344549], - [183, 9, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], - [187, 9, 22, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 500407963], - [198, 9, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], - [204, 9, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], - [208, 9, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], - [208, 89, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], - [209, 9, 19, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2373381424], - [229, 9, 21, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3536149808], - [233, 9, 21, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3536149808], - [308, 9, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 4021964389], - [321, 9, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1127210468], - [322, 32, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1127210468], - [323, 9, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1127210468], - [425, 9, 29, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2816325805], - [434, 9, 32, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 20048093], - [481, 11, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2748649178], - [483, 11, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2748649178], - [494, 9, 9, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 941479953], - [505, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 461316431], - [506, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 461316431], - [559, 9, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1160282543], - [590, 11, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2076032070], - [592, 11, 10, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2076032070], - [635, 60, 12, "Style/GlobalVars: Do not introduce global variables.", 2230010895] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/core_ext/hash_with_indifferent_access.rb:1816584307": [ - [93, 7, 265, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 3153843738] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/group.rb:919076424": [ - [18, 9, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], - [20, 9, 5, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 213462548], - [40, 7, 12, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2641829910], - [46, 7, 18, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 1958067488], - [222, 7, 36, "Performance/InefficientHashSearch: Use `#key?` instead of `#keys.include?`.", 1233002216] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/invocation.rb:15277192": [ - [3, 5, 84, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3488611255], - [113, 7, 68, "Style/InvertibleUnlessCondition: Prefer `if klass > Thor::Base` over `unless klass <= Thor::Base`.", 323464394] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/line_editor.rb:445051654": [ - [6, 5, 98, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1722966001], - [10, 5, 137, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3807720162] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/line_editor/basic.rb:2990814377": [ - [6, 7, 42, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2226661248] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/line_editor/readline.rb:2639491563": [ - [4, 7, 151, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1555432841], - [17, 23, 1, "Lint/AssignmentInCondition: Wrap assignment in parentheses if intentional", 177560] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/parser/argument.rb:1757849163": [ - [28, 26, 3, "Style/AndOr: Use `&&` instead of `and`.", 193409806] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/parser/arguments.rb:2060486072": [ - [8, 5, 220, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3264205835], - [19, 5, 88, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 64145645] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/parser/option.rb:3720922756": [ - [45, 5, 707, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 4238798220], - [153, 48, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550], - [154, 118, 1, "Style/LineEndConcatenation: Use `\\` instead of `+` or `<<` to concatenate those strings.", 177550] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/parser/options.rb:1590095627": [ - [11, 5, 417, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1097829481] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/rake_compat.rb:2680359318": [ - [23, 5, 56, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 120645003], - [24, 7, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 514624543], - [27, 5, 291, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 289349924] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/runner.rb:1283721011": [ - [11, 3, 124, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 1462699376], - [15, 3, 40, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 3579960], - [35, 3, 308, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 2830630606], - [56, 24, 4, "Security/Open: The use of `URI.open` is a serious security risk.", 2087926481], - [72, 26, 4, "Security/Open: The use of `URI.open` is a serious security risk.", 2087926481], - [227, 64, 60, "Performance/InefficientHashSearch: Use `#key?` instead of `#keys.include?`.", 552387362] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/shell.rb:4091723221": [ - [6, 7, 18, "ThreadSafety/ClassAndModuleAttributes: Avoid mutating class and module attributes.", 3758912994], - [12, 9, 6, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2772268155] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/shell/terminal.rb:3147912038": [ - [28, 11, 14, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 3528096361] - ], - "spec/tmp/bundler/gems/thor-1.3.2/lib/thor/util.rb:1633474373": [ - [222, 9, 13, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 4258999585] - ], - "spec/tmp/bundler/gems/waffle-1.0.0/lib/waffle.rb:2896717917": [ - [1, 1, 15, "Style/GlobalVars: Do not introduce global variables.", 2356319643] - ], - "spec/tmp/bundler/specifications/thor-1.3.2.gemspec:4209767878": [ - [24, 3, 79, "Gemspec/DependencyVersion: Dependency version specification is required.", 2841802434] ] } From b91f481f9ce529e8bcb427b0fe6ba6557211c016 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Tue, 25 Feb 2025 00:54:55 +0700 Subject: [PATCH 22/60] =?UTF-8?q?=F0=9F=90=9B=20Ruby=20<=203.0=20compat:?= =?UTF-8?q?=20Bifurcate=20the=20Modern=20Double=20Splat=20(#5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (redux) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (redux deux) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (tiga) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (empat) --- lib/appraisal/appraisal_file.rb | 3 ++- lib/appraisal/customize.rb | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/appraisal/appraisal_file.rb b/lib/appraisal/appraisal_file.rb index 316673fb..1d7b9ec6 100644 --- a/lib/appraisal/appraisal_file.rb +++ b/lib/appraisal/appraisal_file.rb @@ -35,7 +35,8 @@ def appraise(name, &block) end def customize_gemfiles(&_block) - Customize.new(**yield) + args = yield + Customize.new(args) end private diff --git a/lib/appraisal/customize.rb b/lib/appraisal/customize.rb index 8d9e4a75..cc8e08de 100644 --- a/lib/appraisal/customize.rb +++ b/lib/appraisal/customize.rb @@ -2,7 +2,9 @@ module Appraisal class Customize - def initialize(heading: nil, single_quotes: false) + def initialize(options = {}) + heading = options.fetch(:heading, nil) + single_quotes = options.fetch(:single_quotes, false) @@heading = !heading.nil? && heading.chomp @@single_quotes = single_quotes end From 2dffa71a75d569a16e11f9d18b505702cabaca0a Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Tue, 25 Feb 2025 01:10:55 +0700 Subject: [PATCH 23/60] =?UTF-8?q?=F0=9F=9A=A8=20Style/SymbolArray:=20Enfor?= =?UTF-8?q?cedStyle:=20brackets=20(#6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (redux) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (redux deux) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (tiga) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (empat) * 🚨 Style/SymbolArray: EnforcedStyle: brackets - Ruby < 2 compat --- .rubocop.yml | 3 +++ .rubocop_gradual.lock | 10 +++++----- lib/appraisal/bundler_dsl.rb | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 0d8799c6..4f80d90f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -15,3 +15,6 @@ RSpec/DescribeClass: # See: https://coderscat.com/ruby-change-current-working-directory/ ThreadSafety/DirChdir: Enabled: false + +Style/SymbolArray: + EnforcedStyle: brackets diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index fc654a0e..cffcf805 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -7,16 +7,16 @@ "bin/bundle:41466308": [ [66, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] ], - "lib/appraisal/appraisal_file.rb:3486777149": [ + "lib/appraisal/appraisal_file.rb:3950440874": [ [13, 5, 52, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 946226050] ], "lib/appraisal/cli.rb:435288507": [ [116, 5, 410, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 1969529734] ], - "lib/appraisal/customize.rb:190316824": [ - [10, 5, 138, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2682968747], - [17, 5, 62, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 4082816720], - [21, 5, 516, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2780620929] + "lib/appraisal/customize.rb:473220891": [ + [12, 5, 138, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2682968747], + [19, 5, 62, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 4082816720], + [23, 5, 516, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 2780620929] ], "lib/appraisal/utils.rb:3706894031": [ [6, 5, 129, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 733338411], diff --git a/lib/appraisal/bundler_dsl.rb b/lib/appraisal/bundler_dsl.rb index 4e1a4a06..113b6fac 100644 --- a/lib/appraisal/bundler_dsl.rb +++ b/lib/appraisal/bundler_dsl.rb @@ -159,7 +159,7 @@ def dependencies_entry_for_dup @dependencies.for_dup end - %i[gits paths platforms groups source_blocks install_if].each do |method_name| + [:gits, :paths, :platforms, :groups, :source_blocks, :install_if].each do |method_name| class_eval <<-METHODS, __FILE__, __LINE__ + 1 private From a3a3e4b7db67d9b085f96b2ffddd2b51bd8a1196 Mon Sep 17 00:00:00 2001 From: Peter Boling Date: Tue, 25 Feb 2025 03:00:56 +0700 Subject: [PATCH 24/60] LTS Updates (#7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (redux) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (redux deux) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (tiga) * 🐛 Ruby < 3.0 compat: Bifurcate the Modern Double Splat (empat) * 🚨 Style/SymbolArray: EnforcedStyle: brackets - Ruby < 2 compat * 💚 Pend spec failure - Possibly due to bundler issue on MRI and JRuby engines - https://github.com/rubygems/rubygems/issues/8518 * 💚 skip tests that are known to fail on old bundler versions * 💚 turn off truffleruby-head for now --- .github/workflows/main.yml | 4 +++- appraisal.gemspec | 1 + spec/acceptance/bundle_without_spec.rb | 5 ++++- spec/spec_helper.rb | 1 + spec/support/acceptance_test_helpers.rb | 4 ++-- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6cbf79e8..e02a9068 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,7 +27,9 @@ jobs: - jruby - jruby-head - truffleruby - - truffleruby-head + # truffleruby-head is failing. + # TODO: Turn this back on once more important MRI Rubies are validated. + # - truffleruby-head steps: - uses: actions/checkout@v4 diff --git a/appraisal.gemspec b/appraisal.gemspec index 67da5627..533b12e0 100644 --- a/appraisal.gemspec +++ b/appraisal.gemspec @@ -49,4 +49,5 @@ Gem::Specification.new do |s| s.add_development_dependency("activesupport", ">= 3.2.21") s.add_development_dependency("rspec", "~> 3.13") + s.add_development_dependency("rspec-pending_for", "~> 0.1", ">= 0.1.17") end diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index 4194071e..b454adf1 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -2,7 +2,10 @@ RSpec.describe "Bundle without group" do it "config set --local without group is honored by Bundler" do - # pending "config set --local without group support seems broken, see: https://github.com/rubygems/rubygems/issues/8518" + reason = "config set --local without group support seems broken, see: https://github.com/rubygems/rubygems/issues/8518" + # Somehow this spec passes on truffleruby *only*!! + pending_for(:engine => "ruby", :reason => reason) + pending_for(:engine => "jruby", :reason => reason) build_gems %w[pancake orange_juice waffle coffee sausage soda] build_gemfile <<-GEMFILE.strip_heredoc.rstrip diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8eb8a448..1d9f7366 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -16,6 +16,7 @@ # External Libraries require "active_support/core_ext/string/strip" +require "rspec/pending_for" # This library require "support/dependency_helpers" diff --git a/spec/support/acceptance_test_helpers.rb b/spec/support/acceptance_test_helpers.rb index c20ba153..78ce6751 100644 --- a/spec/support/acceptance_test_helpers.rb +++ b/spec/support/acceptance_test_helpers.rb @@ -25,13 +25,13 @@ module AcceptanceTestHelpers before :parallel => true do unless Appraisal::Utils.support_parallel_installation? - pending "This Bundler version does not support --jobs flag." + skip "This Bundler version does not support --jobs flag." end end before :git_local => true do unless Appraisal::Utils.support_git_local_installation? - pending "This Bundler version does not support sourcing gems from git repos on local filesystem." + skip "This Bundler version does not support sourcing gems from git repos on local filesystem." end end From b7d66cef68359395fe2d7c046680ab481592dd00 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Fri, 11 Jul 2025 18:43:18 +0000 Subject: [PATCH 25/60] =?UTF-8?q?=F0=9F=94=A8=20Use=20Ruby=203.4.4=20for?= =?UTF-8?q?=20development?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tool-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tool-versions b/.tool-versions index aba173c5..ca745c6d 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby truffleruby-24.1.2 +ruby 3.4.4 From fd7f243b496f5a43427a7968756e2221bc429262 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Fri, 11 Jul 2025 18:45:21 +0000 Subject: [PATCH 26/60] =?UTF-8?q?=F0=9F=94=A8=20Disable=20thoughtbot's=20d?= =?UTF-8?q?ynamic-security.yml=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/{workflows => disabled}/dynamic-security.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{workflows => disabled}/dynamic-security.yml (100%) diff --git a/.github/workflows/dynamic-security.yml b/.github/disabled/dynamic-security.yml similarity index 100% rename from .github/workflows/dynamic-security.yml rename to .github/disabled/dynamic-security.yml From 55d2277968344e7077f40c49ebd397ff1dcb044b Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Fri, 11 Jul 2025 19:08:56 +0000 Subject: [PATCH 27/60] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Hard=20Fork:=20Renam?= =?UTF-8?q?e=20to=20appraisal2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/main.yml | 4 ++++ Gemfile | 4 ++-- README.md | 4 ++-- appraisal.gemspec | 4 ++-- lib/appraisal2.rb | 3 +++ ...appraisals_file_bundler_dsl_compatibility_spec.rb | 8 ++++---- spec/acceptance/bundle_with_custom_path_spec.rb | 2 +- spec/acceptance/bundle_without_spec.rb | 2 +- spec/acceptance/cli/generate_spec.rb | 4 ++-- spec/acceptance/eval_gemfile_spec.rb | 2 +- spec/acceptance/gemfile_dsl_compatibility_spec.rb | 12 ++++++------ spec/acceptance/gemspec_spec.rb | 4 ++-- spec/support/acceptance_test_helpers.rb | 2 +- 13 files changed, 31 insertions(+), 24 deletions(-) create mode 100644 lib/appraisal2.rb diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e02a9068..12ece062 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -33,13 +33,16 @@ jobs: steps: - uses: actions/checkout@v4 + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} - name: Setup Ruby + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} - name: Update bundler + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} env: RUBY_VERSION: ${{ matrix.ruby }} # See: https://dev.to/galtzo/matrix-ruby-gem-bundler-etc-4kk7 @@ -69,4 +72,5 @@ jobs: bundle install - name: Run tests + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} run: bin/rspec diff --git a/Gemfile b/Gemfile index eecd1d1c..a0e4dff4 100644 --- a/Gemfile +++ b/Gemfile @@ -19,7 +19,7 @@ platform :mri do gem "pry", "~> 0.14" # ruby >= 2.0 end -# This here to make sure appraisal works with Rails 3.0.0. +# This here to make sure appraisal2 works with Rails 3.0.0. gem "thor", "~> 0.14.0" if ruby_version < Gem::Version.new("1.9") @@ -34,7 +34,7 @@ elsif ruby_version < Gem::Version.new("2.7") else # Ruby >= 2.7 we can run style / lint checks via rubocop-gradual with rubocop-lts rules for Ruby 1.8+. # This means we can develop on modern Ruby but remain compatible with ancient Ruby. - # TODO: Replace individual style gems below with modular gemfile, once eval_gemfile support is added to appraisal. + # TODO: Replace individual style gems below with modular gemfile, once eval_gemfile support is added to appraisal2. # eval_gemfile "gemfiles/modular/style.gemfile" # We run rubocop on the latest version of Ruby, # but in support of the oldest supported version of Ruby diff --git a/README.md b/README.md index 2b8da76b..003e3bb3 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ pollute the global namespace, one alternative is Setup ----- -Setting up appraisal requires an `Appraisals` file (similar to a `Gemfile`) in +Setting up appraisal2 requires an `Appraisals` file (similar to a `Gemfile`) in your project root, named "Appraisals" (note the case), and some slight changes to your project's `Rakefile`. @@ -326,7 +326,7 @@ Thank you to all [the contributors][contributors] The names and logos for thoughtbot are trademarks of thoughtbot, inc. [thoughtbot]: http://thoughtbot.com/community -[contributors]: https://github.com/thoughtbot/appraisal/contributors +[contributors]: https://github.com/appraisal-rb/appraisal2/contributors License ------- diff --git a/appraisal.gemspec b/appraisal.gemspec index 533b12e0..a9994e19 100644 --- a/appraisal.gemspec +++ b/appraisal.gemspec @@ -8,12 +8,12 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "appraisal/version" Gem::Specification.new do |s| - s.name = "appraisal" + s.name = "appraisal2" s.version = Appraisal::VERSION.dup s.platform = Gem::Platform::RUBY s.authors = ["Joe Ferris", "Prem Sichanugrist"] s.email = ["jferris@thoughtbot.com", "prem@thoughtbot.com"] - s.homepage = "http://github.com/thoughtbot/appraisal" + s.homepage = "http://github.com/appraisal-rb/appraisal2" s.summary = "Find out what your Ruby gems are worth" s.description = 'Appraisal integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."' s.license = "MIT" diff --git a/lib/appraisal2.rb b/lib/appraisal2.rb new file mode 100644 index 00000000..9147fe77 --- /dev/null +++ b/lib/appraisal2.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative "appraisal" diff --git a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb index 084b9984..23c07f68 100644 --- a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb +++ b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb @@ -54,7 +54,7 @@ gem 'mayonnaise' end - gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + gem 'appraisal2', :path => #{PROJECT_ROOT.inspect} GEMFILE build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip @@ -122,7 +122,7 @@ gem "bagel" gem "croissant", :git => "../../build/croissant" - gem "appraisal", :path => #{PROJECT_ROOT.inspect} + gem "appraisal2", :path => #{PROJECT_ROOT.inspect} gem "bread" gem "pain_au_chocolat", :git => "../../build/pain_au_chocolat" @@ -166,7 +166,7 @@ ruby "#{RUBY_VERSION}#{ruby_dev_append}" - gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + gem 'appraisal2', :path => #{PROJECT_ROOT.inspect} GEMFILE build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip @@ -185,7 +185,7 @@ ruby(:file => ".ruby-version") - gem "appraisal", :path => #{PROJECT_ROOT.inspect} + gem "appraisal2", :path => #{PROJECT_ROOT.inspect} GEMFILE end end diff --git a/spec/acceptance/bundle_with_custom_path_spec.rb b/spec/acceptance/bundle_with_custom_path_spec.rb index f459723c..7cb1a67b 100644 --- a/spec/acceptance/bundle_with_custom_path_spec.rb +++ b/spec/acceptance/bundle_with_custom_path_spec.rb @@ -9,7 +9,7 @@ build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" - gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + gem 'appraisal2', :path => #{PROJECT_ROOT.inspect} if RUBY_VERSION < "1.9" #{File.read(File.join(PROJECT_ROOT, "Gemfile-1.8"))} diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index b454adf1..9d9fdd8b 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -18,7 +18,7 @@ gem "orange_juice" end - gem "appraisal", :path => #{PROJECT_ROOT.inspect} + gem "appraisal2", :path => #{PROJECT_ROOT.inspect} GEMFILE build_appraisal_file <<-APPRAISALS.strip_heredoc.rstrip diff --git a/spec/acceptance/cli/generate_spec.rb b/spec/acceptance/cli/generate_spec.rb index 9c6fdb50..44f48a80 100644 --- a/spec/acceptance/cli/generate_spec.rb +++ b/spec/acceptance/cli/generate_spec.rb @@ -5,7 +5,7 @@ build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" - gem "appraisal", :path => "#{PROJECT_ROOT}" + gem "appraisal2", :path => "#{PROJECT_ROOT}" GEMFILE build_appraisal_file <<-APPRAISAL.strip_heredoc.rstrip @@ -27,7 +27,7 @@ source "https://rubygems.org" - gem "appraisal", :path => "#{PROJECT_ROOT}" + gem "appraisal2", :path => "#{PROJECT_ROOT}" gem "dummy", "1.0.0" GEMFILE end diff --git a/spec/acceptance/eval_gemfile_spec.rb b/spec/acceptance/eval_gemfile_spec.rb index 7ea54c6d..d23ce98d 100644 --- a/spec/acceptance/eval_gemfile_spec.rb +++ b/spec/acceptance/eval_gemfile_spec.rb @@ -14,7 +14,7 @@ write_file "Gemfile", <<-GEMFILE source "https://rubygems.org" - gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + gem 'appraisal2', :path => #{PROJECT_ROOT.inspect} gemspec GEMFILE diff --git a/spec/acceptance/gemfile_dsl_compatibility_spec.rb b/spec/acceptance/gemfile_dsl_compatibility_spec.rb index 6e802218..823bcac3 100644 --- a/spec/acceptance/gemfile_dsl_compatibility_spec.rb +++ b/spec/acceptance/gemfile_dsl_compatibility_spec.rb @@ -26,7 +26,7 @@ gem "waffle" end - gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + gem 'appraisal2', :path => #{PROJECT_ROOT.inspect} gemspec GEMFILE @@ -60,7 +60,7 @@ gem "orange_juice" end - gem "appraisal", :path => #{PROJECT_ROOT.inspect} + gem "appraisal2", :path => #{PROJECT_ROOT.inspect} gem "rice" gem "miso_soup" @@ -90,7 +90,7 @@ gem "orange_juice" end - gem "appraisal", :path => #{PROJECT_ROOT.inspect} + gem "appraisal2", :path => #{PROJECT_ROOT.inspect} gem "bread" group :breakfast do @@ -113,7 +113,7 @@ build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" - gem "appraisal", :path => #{PROJECT_ROOT.inspect} + gem "appraisal2", :path => #{PROJECT_ROOT.inspect} gem "bacon", "1.2.0" GEMFILE @@ -146,7 +146,7 @@ build_gemfile <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" - gem "appraisal", :path => #{PROJECT_ROOT.inspect} + gem "appraisal2", :path => #{PROJECT_ROOT.inspect} group :plugin do gemspec @@ -167,7 +167,7 @@ source "https://rubygems.org" - gem "appraisal", :path => #{PROJECT_ROOT.inspect} + gem "appraisal2", :path => #{PROJECT_ROOT.inspect} gem "bacon", "1.0.0" group :plugin do diff --git a/spec/acceptance/gemspec_spec.rb b/spec/acceptance/gemspec_spec.rb index 1db139cc..505b80bf 100644 --- a/spec/acceptance/gemspec_spec.rb +++ b/spec/acceptance/gemspec_spec.rb @@ -12,7 +12,7 @@ write_file "Gemfile", <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" - gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + gem 'appraisal2', :path => #{PROJECT_ROOT.inspect} gemspec GEMFILE @@ -30,7 +30,7 @@ write_file "Gemfile", <<-GEMFILE.strip_heredoc.rstrip source "https://rubygems.org" - gem 'appraisal', :path => #{PROJECT_ROOT.inspect} + gem 'appraisal2', :path => #{PROJECT_ROOT.inspect} gemspec :path => './specdir' GEMFILE diff --git a/spec/support/acceptance_test_helpers.rb b/spec/support/acceptance_test_helpers.rb index 78ce6751..b721be90 100644 --- a/spec/support/acceptance_test_helpers.rb +++ b/spec/support/acceptance_test_helpers.rb @@ -161,7 +161,7 @@ def build_default_gemfile build_gemfile <<-GEMFILE.strip_heredoc.rstrip source 'https://rubygems.org' - gem 'appraisal', :path => '#{PROJECT_ROOT}' + gem 'appraisal2', :path => '#{PROJECT_ROOT}' GEMFILE run "bundle install --local" From 555e3da222402e2750a6c5af9632421e35327e4e Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Fri, 11 Jul 2025 19:20:23 +0000 Subject: [PATCH 28/60] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20RubyM?= =?UTF-8?q?ine=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 10 + .idea/appraisal2.iml | 86 ++++++++ .idea/dbnavigator.xml | 438 ++++++++++++++++++++++++++++++++++++++ .idea/git_toolbox_prj.xml | 15 ++ .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 7 + 7 files changed, 568 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/appraisal2.iml create mode 100644 .idea/dbnavigator.xml create mode 100644 .idea/git_toolbox_prj.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..a29d697c --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# CodeStream ignored files +/codestream.xml diff --git a/.idea/appraisal2.iml b/.idea/appraisal2.iml new file mode 100644 index 00000000..4e73bc50 --- /dev/null +++ b/.idea/appraisal2.iml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml new file mode 100644 index 00000000..8f9a1232 --- /dev/null +++ b/.idea/dbnavigator.xml @@ -0,0 +1,438 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 00000000..02b915b8 --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..39693f09 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..3f6e41d4 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..83067447 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From c097dd41d80de7ace7abb8eb4a06c60876ae3096 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Fri, 11 Jul 2025 19:48:17 +0000 Subject: [PATCH 29/60] =?UTF-8?q?=F0=9F=90=9B=20Ruby=20<=202=20compat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - no require_relative --- lib/appraisal2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/appraisal2.rb b/lib/appraisal2.rb index 9147fe77..8e220d11 100644 --- a/lib/appraisal2.rb +++ b/lib/appraisal2.rb @@ -1,3 +1,3 @@ # frozen_string_literal: true -require_relative "appraisal" +require "appraisal" From dcf1e96fcf5549c87e12b888cbb12691bd9bb4e9 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Fri, 11 Jul 2025 20:42:09 +0000 Subject: [PATCH 30/60] =?UTF-8?q?=F0=9F=9A=9A=20Rename=20gemspec=20to=20ap?= =?UTF-8?q?praisal2.gemspec?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appraisal.gemspec => appraisal2.gemspec | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename appraisal.gemspec => appraisal2.gemspec (100%) diff --git a/appraisal.gemspec b/appraisal2.gemspec similarity index 100% rename from appraisal.gemspec rename to appraisal2.gemspec From 9be490a03647f0c88406adc5d5b102f61a956180 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 13 Jul 2025 22:30:56 +0000 Subject: [PATCH 31/60] =?UTF-8?q?=F0=9F=91=B7=20Expand=20CI=20as=20much=20?= =?UTF-8?q?as=20possible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .envrc | 37 + .github/workflows/codeql-analysis.yml | 71 + .github/workflows/coverage.yml | 120 + .github/workflows/current-runtime-heads.yml | 89 + .github/workflows/current.yml | 83 + .github/workflows/dependency-review.yml | 21 + .github/workflows/heads.yml | 83 + .github/workflows/jruby-9-4.yml | 68 + .github/workflows/main.yml | 76 - .github/workflows/ruby-2-3.yml | 64 + .github/workflows/ruby-2-4.yml | 64 + .github/workflows/ruby-2-5.yml | 64 + .github/workflows/ruby-2-6.yml | 64 + .github/workflows/ruby-2-7.yml | 64 + .github/workflows/ruby-3-0.yml | 64 + .github/workflows/ruby-3-1.yml | 64 + .github/workflows/ruby-3-2.yml | 62 + .github/workflows/ruby-3-3.yml | 64 + .github/workflows/style.yml | 62 + .gitignore | 50 +- .idea/GitLink.xml | 6 + .idea/appraisal2.iml | 3034 ++++++++++++++++- .rubocop_gradual.lock | 12 +- .simplecov | 3 + .yard_gfm_support.rb | 22 + .yardopts | 11 + Appraisal.root.gemfile | 15 + Appraisals | 95 + Gemfile | 119 +- Gemfile.lock | 297 ++ README.md | 2 +- Rakefile | 125 +- appraisal2.gemspec | 72 +- bin/appraisal | 27 + bin/bundle-audit | 27 + bin/bundler-audit | 27 + bin/code_climate_reek | 27 + bin/coderay | 27 + bin/erb | 27 + bin/htmldiff | 27 + bin/irb | 27 + bin/kramdown | 27 + bin/ldiff | 27 + bin/nokogiri | 27 + bin/pry | 27 + bin/racc | 27 + bin/rake | 27 + bin/rake2thor | 27 + bin/rdbg | 27 + bin/rdoc | 27 + bin/reek | 27 + bin/ri | 27 + bin/rubocop | 27 + bin/rubocop-gradual | 27 + bin/ruby-parse | 27 + bin/ruby-rewrite | 27 + bin/standardrb | 27 + bin/thor | 27 + bin/yard | 27 + bin/yard-junk | 27 + bin/yardoc | 27 + bin/yri | 27 + exe/appraisal | 2 +- gemfiles/audit.gemfile | 7 + gemfiles/coverage.gemfile | 7 + gemfiles/current.gemfile | 7 + gemfiles/dep_heads.gemfile | 7 + gemfiles/heads.gemfile | 7 + gemfiles/modular/audit.gemfile | 5 + gemfiles/modular/coverage.gemfile | 11 + gemfiles/modular/current.gemfile | 3 + gemfiles/modular/debug.gemfile | 8 + gemfiles/modular/documentation.gemfile | 11 + gemfiles/modular/heads.gemfile | 1 + gemfiles/modular/logger/r2/v1.5.gemfile | 3 + gemfiles/modular/logger/r3/v1.7.gemfile | 2 + gemfiles/modular/logger/vHEAD.gemfile | 2 + gemfiles/modular/ruby_1_8.gemfile | 11 + gemfiles/modular/ruby_1_9.gemfile | 9 + gemfiles/modular/ruby_2_0.gemfile | 9 + gemfiles/modular/ruby_2_1.gemfile | 9 + gemfiles/modular/ruby_2_2.gemfile | 5 + gemfiles/modular/ruby_2_3.gemfile | 5 + gemfiles/modular/ruby_2_4.gemfile | 5 + gemfiles/modular/ruby_2_5.gemfile | 5 + gemfiles/modular/ruby_2_6.gemfile | 5 + gemfiles/modular/ruby_2_7.gemfile | 5 + gemfiles/modular/ruby_3_0.gemfile | 5 + gemfiles/modular/ruby_3_1.gemfile | 5 + gemfiles/modular/ruby_3_2.gemfile | 5 + gemfiles/modular/ruby_3_3.gemfile | 5 + gemfiles/modular/runtime_heads.gemfile | 9 + gemfiles/modular/style.gemfile | 7 +- gemfiles/modular/thor/r1/v0.20.gemfile | 2 + gemfiles/modular/thor/r2.6/v1.3.gemfile | 2 + gemfiles/modular/thor/r2/v1.2.gemfile | 2 + gemfiles/modular/thor/r3/v1.3.gemfile | 2 + gemfiles/modular/thor/vHEAD.gemfile | 2 + gemfiles/modular/uri/r2/v0.gemfile | 2 + gemfiles/modular/uri/r3/v1.gemfile | 2 + gemfiles/modular/uri/vHEAD.gemfile | 2 + gemfiles/modular/x_std_libs/r1/libs.gemfile | 2 + gemfiles/modular/x_std_libs/r2/libs.gemfile | 2 + gemfiles/modular/x_std_libs/r3/libs.gemfile | 2 + gemfiles/modular/x_std_libs/vHEAD.gemfile | 2 + gemfiles/ruby_1_8.gemfile | 7 + gemfiles/ruby_1_9.gemfile | 7 + gemfiles/ruby_2_0.gemfile | 7 + gemfiles/ruby_2_1.gemfile | 7 + gemfiles/ruby_2_2.gemfile | 7 + gemfiles/ruby_2_3.gemfile | 7 + gemfiles/ruby_2_4.gemfile | 7 + gemfiles/ruby_2_5.gemfile | 7 + gemfiles/ruby_2_6.gemfile | 7 + gemfiles/ruby_2_7.gemfile | 7 + gemfiles/ruby_3_0.gemfile | 7 + gemfiles/ruby_3_1.gemfile | 7 + gemfiles/ruby_3_2.gemfile | 7 + gemfiles/ruby_3_3.gemfile | 7 + gemfiles/style.gemfile | 7 + lib/appraisal/appraisal.rb | 7 +- lib/appraisal/cli.rb | 2 +- lib/appraisal/dependency_list.rb | 5 +- lib/appraisal/version.rb | 2 +- ...als_file_bundler_dsl_compatibility_spec.rb | 2 +- .../bundle_with_custom_path_spec.rb | 8 +- spec/acceptance/cli/version_spec.rb | 6 +- spec/acceptance/eval_gemfile_spec.rb | 2 - spec/appraisal/appraisal_file_spec.rb | 3 +- spec/appraisal/appraisal_spec.rb | 1 - spec/appraisal/customize_spec.rb | 1 - spec/appraisal/dependency_list_spec.rb | 1 - spec/appraisal/gemfile_spec.rb | 1 - spec/appraisal/utils_spec.rb | 1 - spec/config/byebug.rb | 11 + spec/config/rspec/rspec_block_is_expected.rb | 2 + spec/config/rspec/rspec_core.rb | 30 + spec/fixtures/Gemfile-1.8 | 6 + spec/fixtures/Gemfile-2.0 | 4 + spec/fixtures/Gemfile-2.1 | 4 + spec/spec_helper.rb | 55 +- spec/support/acceptance_test_helpers.rb | 4 + 142 files changed, 6106 insertions(+), 298 deletions(-) create mode 100644 .envrc create mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 .github/workflows/coverage.yml create mode 100644 .github/workflows/current-runtime-heads.yml create mode 100644 .github/workflows/current.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 .github/workflows/heads.yml create mode 100644 .github/workflows/jruby-9-4.yml delete mode 100644 .github/workflows/main.yml create mode 100755 .github/workflows/ruby-2-3.yml create mode 100755 .github/workflows/ruby-2-4.yml create mode 100755 .github/workflows/ruby-2-5.yml create mode 100644 .github/workflows/ruby-2-6.yml create mode 100644 .github/workflows/ruby-2-7.yml create mode 100644 .github/workflows/ruby-3-0.yml create mode 100644 .github/workflows/ruby-3-1.yml create mode 100644 .github/workflows/ruby-3-2.yml create mode 100644 .github/workflows/ruby-3-3.yml create mode 100644 .github/workflows/style.yml create mode 100644 .idea/GitLink.xml create mode 100644 .simplecov create mode 100644 .yard_gfm_support.rb create mode 100644 .yardopts create mode 100755 Appraisal.root.gemfile create mode 100644 Appraisals create mode 100644 Gemfile.lock create mode 100755 bin/appraisal create mode 100755 bin/bundle-audit create mode 100755 bin/bundler-audit create mode 100755 bin/code_climate_reek create mode 100755 bin/coderay create mode 100755 bin/erb create mode 100755 bin/htmldiff create mode 100755 bin/irb create mode 100755 bin/kramdown create mode 100755 bin/ldiff create mode 100755 bin/nokogiri create mode 100755 bin/pry create mode 100755 bin/racc create mode 100755 bin/rake create mode 100755 bin/rake2thor create mode 100755 bin/rdbg create mode 100755 bin/rdoc create mode 100755 bin/reek create mode 100755 bin/ri create mode 100755 bin/rubocop create mode 100755 bin/rubocop-gradual create mode 100755 bin/ruby-parse create mode 100755 bin/ruby-rewrite create mode 100755 bin/standardrb create mode 100755 bin/thor create mode 100755 bin/yard create mode 100755 bin/yard-junk create mode 100755 bin/yardoc create mode 100755 bin/yri create mode 100644 gemfiles/audit.gemfile create mode 100644 gemfiles/coverage.gemfile create mode 100644 gemfiles/current.gemfile create mode 100644 gemfiles/dep_heads.gemfile create mode 100644 gemfiles/heads.gemfile create mode 100644 gemfiles/modular/audit.gemfile create mode 100644 gemfiles/modular/coverage.gemfile create mode 100644 gemfiles/modular/current.gemfile create mode 100644 gemfiles/modular/debug.gemfile create mode 100755 gemfiles/modular/documentation.gemfile create mode 100644 gemfiles/modular/heads.gemfile create mode 100644 gemfiles/modular/logger/r2/v1.5.gemfile create mode 100644 gemfiles/modular/logger/r3/v1.7.gemfile create mode 100644 gemfiles/modular/logger/vHEAD.gemfile create mode 100644 gemfiles/modular/ruby_1_8.gemfile create mode 100644 gemfiles/modular/ruby_1_9.gemfile create mode 100644 gemfiles/modular/ruby_2_0.gemfile create mode 100644 gemfiles/modular/ruby_2_1.gemfile create mode 100644 gemfiles/modular/ruby_2_2.gemfile create mode 100644 gemfiles/modular/ruby_2_3.gemfile create mode 100644 gemfiles/modular/ruby_2_4.gemfile create mode 100644 gemfiles/modular/ruby_2_5.gemfile create mode 100644 gemfiles/modular/ruby_2_6.gemfile create mode 100644 gemfiles/modular/ruby_2_7.gemfile create mode 100644 gemfiles/modular/ruby_3_0.gemfile create mode 100644 gemfiles/modular/ruby_3_1.gemfile create mode 100644 gemfiles/modular/ruby_3_2.gemfile create mode 100644 gemfiles/modular/ruby_3_3.gemfile create mode 100644 gemfiles/modular/runtime_heads.gemfile create mode 100644 gemfiles/modular/thor/r1/v0.20.gemfile create mode 100644 gemfiles/modular/thor/r2.6/v1.3.gemfile create mode 100644 gemfiles/modular/thor/r2/v1.2.gemfile create mode 100644 gemfiles/modular/thor/r3/v1.3.gemfile create mode 100644 gemfiles/modular/thor/vHEAD.gemfile create mode 100644 gemfiles/modular/uri/r2/v0.gemfile create mode 100644 gemfiles/modular/uri/r3/v1.gemfile create mode 100644 gemfiles/modular/uri/vHEAD.gemfile create mode 100644 gemfiles/modular/x_std_libs/r1/libs.gemfile create mode 100644 gemfiles/modular/x_std_libs/r2/libs.gemfile create mode 100644 gemfiles/modular/x_std_libs/r3/libs.gemfile create mode 100644 gemfiles/modular/x_std_libs/vHEAD.gemfile create mode 100644 gemfiles/ruby_1_8.gemfile create mode 100644 gemfiles/ruby_1_9.gemfile create mode 100644 gemfiles/ruby_2_0.gemfile create mode 100644 gemfiles/ruby_2_1.gemfile create mode 100644 gemfiles/ruby_2_2.gemfile create mode 100644 gemfiles/ruby_2_3.gemfile create mode 100644 gemfiles/ruby_2_4.gemfile create mode 100644 gemfiles/ruby_2_5.gemfile create mode 100644 gemfiles/ruby_2_6.gemfile create mode 100644 gemfiles/ruby_2_7.gemfile create mode 100644 gemfiles/ruby_3_0.gemfile create mode 100644 gemfiles/ruby_3_1.gemfile create mode 100644 gemfiles/ruby_3_2.gemfile create mode 100644 gemfiles/ruby_3_3.gemfile create mode 100644 gemfiles/style.gemfile create mode 100644 spec/config/byebug.rb create mode 100644 spec/config/rspec/rspec_block_is_expected.rb create mode 100644 spec/config/rspec/rspec_core.rb create mode 100644 spec/fixtures/Gemfile-1.8 create mode 100644 spec/fixtures/Gemfile-2.0 create mode 100644 spec/fixtures/Gemfile-2.1 diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..7d45c9c9 --- /dev/null +++ b/.envrc @@ -0,0 +1,37 @@ +# Run any command in this library's bin/ without the bin/ prefix! +PATH_add bin + +# Only add things to this file that should be shared with the team. + +# **dotenv** (See end of file for .env.local integration) +# .env would override anything in this file, if enabled. +# .env is a DOCKER standard, and if we use it, it would be in deployed, or DOCKER, environments. +# Override and customize anything below in your own .env.local +# If you are using dotenv and not direnv, +# copy the following `export` statements to your own .env file. + +### General Ruby ### +# Turn off Ruby Warnings about deprecated code +# export RUBYOPT="-W0" + +### External Testing Controls +export K_SOUP_COV_DO=true # Means you want code coverage +# Available formats are html, xml, rcov, lcov, json, tty +export K_SOUP_COV_COMMAND_NAME="Test Coverage" +export K_SOUP_COV_FORMATTERS="html,tty" +export K_SOUP_COV_MIN_BRANCH=76 # Means you want to enforce X% branch coverage +export K_SOUP_COV_MIN_LINE=90 # Means you want to enforce X% line coverage +export K_SOUP_COV_MIN_HARD=true # Means you want the build to fail if the coverage thresholds are not met +export K_SOUP_COV_MULTI_FORMATTERS=true +export MAX_ROWS=1 # Setting for simplecov-console gem for tty output, limits to the worst N rows of bad coverage + +# Internal Debugging Controls +export DEBUG=false # do not allow byebug statements (override in .env.local) + +# .env would override anything in this file, if `dotenv` is uncommented below. +# .env is a DOCKER standard, and if we use it, it would be in deployed, or DOCKER, environments, +# and that is why we generally want to leave it commented out. +# dotenv + +# .env.local will override anything in this file. +dotenv_if_exists .env.local diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..d2e359c1 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,71 @@ +--- +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ main, "*-stable" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main, "*-stable" ] + schedule: + - cron: '35 1 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'ruby' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000..f3aadc58 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,120 @@ +--- +# Targets the evergreen latest release of ruby +name: Test Coverage + +permissions: + contents: read + pull-requests: write + id-token: write + +env: + COVERAGE_GEMS: true + K_SOUP_COV_MIN_BRANCH: 85 + K_SOUP_COV_MIN_LINE: 91 + K_SOUP_COV_MIN_HARD: true + K_SOUP_COV_FORMATTERS: "html,xml,rcov,lcov,json,tty" + K_SOUP_COV_DO: true + K_SOUP_COV_MULTI_FORMATTERS: true + K_SOUP_COV_COMMAND_NAME: "Test Coverage" + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + coverage: + name: Code Coverage ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby + - ruby: "ruby" + gemfile: "coverage" + exec_cmd: "rake test" + rubygems: latest + bundler: latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: "${{ matrix.ruby }}" + rubygems: "${{ matrix.rubygems }}" + bundler: "${{ matrix.bundler }}" + - name: bundle install + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} + + # Do SaaS coverage uploads first + - name: Upload coverage to Coveralls + if: ${{ !env.ACT }} + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload coverage to QLTY + if: ${{ !env.ACT }} + uses: qltysh/qlty-action/coverage@main + with: + token: ${{secrets.QLTY_COVERAGE_TOKEN}} + files: coverage/.resultset.json + + # Build will fail here if coverage upload fails + # which will hopefully be noticed for the lack of code coverage comments + - name: Upload coverage to CodeCov + if: ${{ !env.ACT }} + uses: codecov/codecov-action@v5 + with: + use_oidc: true + fail_ci_if_error: true # optional (default = false) + verbose: true # optional (default = false) + + # Then PR comments + - name: Code Coverage Summary Report + if: ${{ !env.ACT && github.event_name == 'pull_request' }} + uses: irongut/CodeCoverageSummary@v1.3.0 + with: + filename: ./coverage/coverage.xml + badge: true + fail_below_min: true + format: markdown + hide_branch_rate: false + hide_complexity: true + indicators: true + output: both + thresholds: '91 85' + + - name: Add Coverage PR Comment + if: ${{ !env.ACT && github.event_name == 'pull_request' }} + uses: marocchino/sticky-pull-request-comment@v2 + with: + recreate: true + path: code-coverage-results.md diff --git a/.github/workflows/current-runtime-heads.yml b/.github/workflows/current-runtime-heads.yml new file mode 100644 index 00000000..df291ba7 --- /dev/null +++ b/.github/workflows/current-runtime-heads.yml @@ -0,0 +1,89 @@ +--- +# Targets the evergreen latest release of ruby, truffleruby, and jruby +# and tests against the HEAD of runtime dependencies +name: Runtime Deps @ HEAD + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby + - ruby: "ruby" + gemfile: "dep-heads" + exec_cmd: "rake test" + rubygems: latest + bundler: latest + + # truffleruby + - ruby: "truffleruby" + gemfile: "dep-heads" + exec_cmd: "rake test" + experimental: true + rubygems: default + bundler: default + + # jruby + - ruby: "jruby" + gemfile: "dep-heads" + exec_cmd: "rake test" + experimental: true + rubygems: default + bundler: default + + steps: + - name: Checkout + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + continue-on-error: ${{ matrix.experimental != 'false' }} + + - name: bundle install + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + continue-on-error: ${{ matrix.experimental != 'false' }} + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} + continue-on-error: ${{ matrix.experimental != 'false' }} diff --git a/.github/workflows/current.yml b/.github/workflows/current.yml new file mode 100644 index 00000000..338fcb59 --- /dev/null +++ b/.github/workflows/current.yml @@ -0,0 +1,83 @@ +--- +# Targets the evergreen latest release of ruby, truffleruby, and jruby +name: Current + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby + - ruby: "ruby" + gemfile: "current" + exec_cmd: "rake test" + rubygems: latest + bundler: latest + + # truffleruby + - ruby: "truffleruby" + gemfile: "current" + exec_cmd: "rake test" + rubygems: default + bundler: default + + # jruby + - ruby: "jruby" + gemfile: "current" + exec_cmd: "rake test" + rubygems: default + bundler: default + + steps: + - name: Checkout + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 00000000..9a20f45c --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,21 @@ +--- +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v4 diff --git a/.github/workflows/heads.yml b/.github/workflows/heads.yml new file mode 100644 index 00000000..14212a07 --- /dev/null +++ b/.github/workflows/heads.yml @@ -0,0 +1,83 @@ +--- +name: Heads + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: true + matrix: + include: + # NOTE: Heads use default rubygems / bundler; their defaults are custom, unreleased, and from the future! + # ruby-head + - ruby: "ruby-head" + gemfile: "heads" + exec_cmd: "rake test" + rubygems: default + bundler: default + +# # truffleruby-head + - ruby: "truffleruby-head" + gemfile: "heads" + exec_cmd: "rake test" + rubygems: default + bundler: default + + # jruby-head + - ruby: "jruby-head" + gemfile: "heads" + exec_cmd: "rake test" + rubygems: default + bundler: default + + steps: + - name: Checkout + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/jruby-9-4.yml b/.github/workflows/jruby-9-4.yml new file mode 100644 index 00000000..c2eb0c9e --- /dev/null +++ b/.github/workflows/jruby-9-4.yml @@ -0,0 +1,68 @@ +--- +name: JRuby 9.4 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # jruby-9.4 (targets Ruby 3.1 compatibility) + - ruby: "jruby-9.4" + gemfile: "ruby_3_1" + exec_cmd: "rake test" + rubygems: default + bundler: default + + steps: + - name: Checkout + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + if: ${{ !env.ACT || (env.ACT && !startsWith(matrix.ruby, 'jruby')) }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 12ece062..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,76 +0,0 @@ ---- -name: Tests - -on: - push: - branches: - - '**' - pull_request: - branches: - - '**' - -jobs: - test: - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - ruby: - - '3.4' - - '3.3' - - '3.2' - - '3.1' - - '3.0' - - '2.7' - - 'head' - - jruby - - jruby-head - - truffleruby - # truffleruby-head is failing. - # TODO: Turn this back on once more important MRI Rubies are validated. - # - truffleruby-head - - steps: - - uses: actions/checkout@v4 - if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} - - - name: Setup Ruby - if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - - - name: Update bundler - if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} - env: - RUBY_VERSION: ${{ matrix.ruby }} - # See: https://dev.to/galtzo/matrix-ruby-gem-bundler-etc-4kk7 - run: | - case ${RUBY_VERSION} in - 1.8|1.9|2.0|2.1|2.2) - gem install bundler -v 1.17.3 - ;; - - 2.3|2.4|2.5) - gem install bundler -v 2.3.27 - ;; - - 2.6|2.7) - gem install bundler -v 2.4.22 - ;; - - 3.0) - gem install bundler -v 2.5.23 - ;; - - *) - gem update --system - ;; - esac - - bundle install - - - name: Run tests - if: ${{ !env.ACT || !startsWith(matrix.ruby, 'jruby') }} - run: bin/rspec diff --git a/.github/workflows/ruby-2-3.yml b/.github/workflows/ruby-2-3.yml new file mode 100755 index 00000000..a3d69609 --- /dev/null +++ b/.github/workflows/ruby-2-3.yml @@ -0,0 +1,64 @@ +--- +name: MRI 2.3 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 2.3 + - ruby: "ruby-2.3" + gemfile: "ruby_2_3" + exec_cmd: "rake test" + rubygems: "3.3.27" + bundler: "2.3.27" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/ruby-2-4.yml b/.github/workflows/ruby-2-4.yml new file mode 100755 index 00000000..96d45803 --- /dev/null +++ b/.github/workflows/ruby-2-4.yml @@ -0,0 +1,64 @@ +--- +name: MRI 2.4 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 2.4 + - ruby: "ruby-2.4" + gemfile: "ruby_2_4" + exec_cmd: "rake test" + rubygems: "3.3.27" + bundler: "2.3.27" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/ruby-2-5.yml b/.github/workflows/ruby-2-5.yml new file mode 100755 index 00000000..02e13d90 --- /dev/null +++ b/.github/workflows/ruby-2-5.yml @@ -0,0 +1,64 @@ +--- +name: MRI 2.5 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 2.5 + - ruby: "ruby-2.5" + gemfile: "ruby_2_5" + exec_cmd: "rake test" + rubygems: "3.3.27" + bundler: "2.3.27" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/ruby-2-6.yml b/.github/workflows/ruby-2-6.yml new file mode 100644 index 00000000..312c5aed --- /dev/null +++ b/.github/workflows/ruby-2-6.yml @@ -0,0 +1,64 @@ +--- +name: MRI 2.6 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 2.6 + - ruby: "ruby-2.6" + gemfile: "ruby_2_6" + exec_cmd: "rake test" + rubygems: '3.4.22' + bundler: '2.4.22' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/ruby-2-7.yml b/.github/workflows/ruby-2-7.yml new file mode 100644 index 00000000..95512153 --- /dev/null +++ b/.github/workflows/ruby-2-7.yml @@ -0,0 +1,64 @@ +--- +name: MRI 2.7 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 2.7 + - ruby: "ruby-2.7" + gemfile: "ruby_2_7" + exec_cmd: "rake test" + rubygems: '3.4.22' + bundler: '2.4.22' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/ruby-3-0.yml b/.github/workflows/ruby-3-0.yml new file mode 100644 index 00000000..36ab412a --- /dev/null +++ b/.github/workflows/ruby-3-0.yml @@ -0,0 +1,64 @@ +--- +name: MRI 3.0 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 3.0 + - ruby: "ruby-3.0" + gemfile: "ruby_3_0" + exec_cmd: "rake test" + rubygems: '3.5.23' + bundler: '2.5.23' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/ruby-3-1.yml b/.github/workflows/ruby-3-1.yml new file mode 100644 index 00000000..f3e7c77e --- /dev/null +++ b/.github/workflows/ruby-3-1.yml @@ -0,0 +1,64 @@ +--- +name: MRI 3.1 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 3.1 + - ruby: "ruby-3.1" + gemfile: "ruby_3_1" + exec_cmd: "rake test" + rubygems: latest + bundler: latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/ruby-3-2.yml b/.github/workflows/ruby-3-2.yml new file mode 100644 index 00000000..73619238 --- /dev/null +++ b/.github/workflows/ruby-3-2.yml @@ -0,0 +1,62 @@ +--- +name: MRI 3.2 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + strategy: + fail-fast: false + matrix: + include: + # Ruby 3.2 + - ruby: "ruby-3.2" + gemfile: "ruby_3_2" + exec_cmd: "rake test" + rubygems: latest + bundler: latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/ruby-3-3.yml b/.github/workflows/ruby-3-3.yml new file mode 100644 index 00000000..df803876 --- /dev/null +++ b/.github/workflows/ruby-3-3.yml @@ -0,0 +1,64 @@ +--- +name: MRI 3.3 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Tests ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 3.3 + - ruby: "ruby-3.3" + gemfile: "ruby_3_3" + exec_cmd: "rake test" + rubygems: latest + bundler: latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml new file mode 100644 index 00000000..b154d9f3 --- /dev/null +++ b/.github/workflows/style.yml @@ -0,0 +1,62 @@ +--- +# Targets the evergreen latest release of ruby +name: Style + +permissions: + contents: read + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + style: + name: Style ${{ matrix.ruby }} gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.name_extra || '' }} + if: ${{ !contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]') }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + # NOTE: This does not use the primary Gemfile at all. + env: # $BUNDLE_GEMFILE - set at job level, so applies to all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby + - ruby: "ruby" + gemfile: "style" + exec_cmd: "rake rubocop_gradual:check" + rubygems: latest + bundler: latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + - name: bundle install + run: bundle install --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} + run: bundle exec --gemfile ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile ${{ matrix.exec_cmd }} diff --git a/.gitignore b/.gitignore index 46fa9b6b..3a031903 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,49 @@ +# Build Artifacts +/pkg/ +/tmp/ +*.gem + +# Bundler +/.bundle/ +/gemfiles/*.lock +/gemfiles/.bundle/ +/gemfiles/.bundle/config +/gemfiles/vendor/ +Appraisal.*.gemfile.lock +/vendor/ + +# Specs +.rspec_status +/coverage/ +/spec/reports/ + +# Documentation +/.yardoc/ +/_yardoc/ +/rdoc/ +/doc/ + +# Ruby Version Managers (RVM, rbenv, etc) +# Ignored because we currently use .tool-versions +.rvmrc +.ruby-version +.ruby-gemset + +# Benchmarking +/measurement/ + +# Debugger detritus +.byebug_history + +# direnv - brew install direnv +.env.local + +# OS Detritus +.DS_Store *.swp tmp -pkg .swo *~ -*.gem -Gemfile.lock -.bundle -.DS_Store -spec/tmp +# Editors +*~ diff --git a/.idea/GitLink.xml b/.idea/GitLink.xml new file mode 100644 index 00000000..009597cc --- /dev/null +++ b/.idea/GitLink.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/appraisal2.iml b/.idea/appraisal2.iml index 4e73bc50..327172e3 100644 --- a/.idea/appraisal2.iml +++ b/.idea/appraisal2.iml @@ -8,79 +8,2971 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index cffcf805..3367ae73 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -1,8 +1,8 @@ { - "Gemfile:3872962921": [ - [26, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [28, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [30, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] + "Gemfile:2056742212": [ + [41, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [43, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], + [45, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] ], "bin/bundle:41466308": [ [66, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] @@ -31,7 +31,7 @@ "spec/acceptance/cli/clean_spec.rb:1564995421": [ [3, 23, 17, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 1606893221] ], - "spec/acceptance/cli/generate_spec.rb:245350726": [ + "spec/acceptance/cli/generate_spec.rb:3842740582": [ [3, 23, 20, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3905826443] ], "spec/acceptance/cli/help_spec.rb:3569358941": [ @@ -103,7 +103,7 @@ "spec/appraisal/utils_spec.rb:2286225770": [ [62, 17, 58, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 1573223692] ], - "spec/support/acceptance_test_helpers.rb:3072478660": [ + "spec/support/acceptance_test_helpers.rb:3908433317": [ [149, 5, 32, "Style/InvertibleUnlessCondition: Prefer `if $?.exitstatus == 0` over `unless $?.exitstatus != 0`.", 4187517264] ], "spec/support/stream_helpers.rb:3654818709": [ diff --git a/.simplecov b/.simplecov new file mode 100644 index 00000000..bfe90c08 --- /dev/null +++ b/.simplecov @@ -0,0 +1,3 @@ +require "kettle/soup/cover/config" + +SimpleCov.start diff --git a/.yard_gfm_support.rb b/.yard_gfm_support.rb new file mode 100644 index 00000000..49dde5f8 --- /dev/null +++ b/.yard_gfm_support.rb @@ -0,0 +1,22 @@ +# Gratefully and liberally taken from the MIT-licensed https://github.com/bensheldon/good_job/pull/113/files +require "kramdown" +require "kramdown-parser-gfm" + +# Custom markup provider class that always renders Kramdown using GFM (Github Flavored Markdown). +# GFM is needed to render markdown tables and fenced code blocks in the README. +class KramdownGfmDocument < Kramdown::Document + def initialize(source, options = {}) + options[:input] = "GFM" unless options.key?(:input) + super(source, options) + end +end + +# Insert the new provider as the highest priority option for Markdown. +# See: +# - https://github.com/lsegal/yard/issues/1157 +# - https://github.com/lsegal/yard/issues/1017 +# - https://github.com/lsegal/yard/blob/main/lib/yard/templates/helpers/markup_helper.rb +YARD::Templates::Helpers::MarkupHelper::MARKUP_PROVIDERS[:markdown].insert( + 0, + {:const => "KramdownGfmDocument"}, +) diff --git a/.yardopts b/.yardopts new file mode 100644 index 00000000..479134df --- /dev/null +++ b/.yardopts @@ -0,0 +1,11 @@ +--plugin junk +--plugin relative_markdown_links +--readme README.md +--charset utf-8 +--markup markdown +--output docs +--load .yard_gfm_support.rb +'lib/**/*.rb' +- +'*.md' +'*.txt' \ No newline at end of file diff --git a/Appraisal.root.gemfile b/Appraisal.root.gemfile new file mode 100755 index 00000000..07b185fa --- /dev/null +++ b/Appraisal.root.gemfile @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + +source "https://rubygems.org" + +# Appraisal Root Gemfile is for running appraisal to generate the Appraisal Gemfiles +# in gemfiles/*gemfile. +# On CI, we use it for the Appraisal-based builds. +# We do not load the standard Gemfile, as it is tailored for local development. + +# NOTE: Due to variations in relative pathing, we can't use the gemfiles/modular gemfiles here, +# since they would be added to the Appraisals gemfiles with the wrong relative path. + +gemspec diff --git a/Appraisals b/Appraisals new file mode 100644 index 00000000..67380a61 --- /dev/null +++ b/Appraisals @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +# HOW TO UPDATE APPRAISALS: +# BUNDLE_GEMFILE=Appraisal.root.gemfile bundle +# BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal update +# bundle exec rake rubocop_gradual:autocorrect +# NOTE: We do not run specs with appraisals, because that's appraisal-inception. +# Instead, BUNDLE_GEMFILE in each CI run targets an appraisal. + +# Used for HEAD (nightly) releases of ruby, truffleruby, and jruby. +# Split into discrete appraisals if one of them needs a dependency locked discretely. +appraise "dep-heads" do + eval_gemfile "modular/runtime_heads.gemfile" +end + +appraise "ruby-1-8" do + eval_gemfile "modular/ruby_1_8.gemfile" +end + +appraise "ruby-1-9" do + eval_gemfile "modular/ruby_1_9.gemfile" +end + +appraise "ruby-2-0" do + eval_gemfile "modular/ruby_2_0.gemfile" +end + +appraise "ruby-2-1" do + eval_gemfile "modular/ruby_2_1.gemfile" +end + +appraise "ruby-2-2" do + eval_gemfile "modular/ruby_2_2.gemfile" +end + +appraise "ruby-2-3" do + eval_gemfile "modular/ruby_2_3.gemfile" +end + +appraise "ruby-2-4" do + eval_gemfile "modular/ruby_2_4.gemfile" +end + +appraise "ruby-2-5" do + eval_gemfile "modular/ruby_2_5.gemfile" +end + +appraise "ruby-2-6" do + eval_gemfile "modular/ruby_2_6.gemfile" +end + +appraise "ruby-2-7" do + eval_gemfile "modular/ruby_2_7.gemfile" +end + +appraise "ruby-3-0" do + eval_gemfile "modular/ruby_3_0.gemfile" +end + +appraise "ruby-3-1" do + eval_gemfile "modular/ruby_3_1.gemfile" +end + +appraise "ruby-3-2" do + eval_gemfile "modular/ruby_3_2.gemfile" +end + +appraise "ruby-3-3" do + eval_gemfile "modular/ruby_3_3.gemfile" +end + +# Used for current releases of ruby, truffleruby, and jruby. +# Split into discrete appraisals if one of them needs a dependency locked discretely. +appraise "current" do + eval_gemfile "modular/current.gemfile" +end + +appraise "heads" do + eval_gemfile "modular/heads.gemfile" +end + +# Only run security audit on the latest version of Ruby +appraise "audit" do + eval_gemfile "modular/audit.gemfile" +end + +# Only run coverage on the latest version of Ruby +appraise "coverage" do + eval_gemfile "modular/coverage.gemfile" +end + +# Only run linter on the latest version of Ruby (but, in support of the oldest supported Ruby version) +appraise "style" do + eval_gemfile "modular/style.gemfile" +end diff --git a/Gemfile b/Gemfile index a0e4dff4..11c6047f 100644 --- a/Gemfile +++ b/Gemfile @@ -1,48 +1,95 @@ +#### IMPORTANT ####################################################### +# Gemfile is for local development ONLY; Gemfile is NOT loaded in CI # +####################################################### IMPORTANT #### +# On CI we only need the gemspecs' dependencies (including development dependencies). +# Exceptions, if any, such as for Appraisals, are in gemfiles/*.gemfile + source "https://rubygems.org" -gemspec +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } +git_source(:gitlab) { |repo_name| "https://gitlab.com/#{repo_name}" } -# For Ruby version specific dependencies -ruby_version = Gem::Version.new(RUBY_VERSION) +latest_ruby_version = Gem::Version.create("3.4") +current_ruby_version = Gem::Version.create(RUBY_VERSION) +current_minor_ruby = Gem::Version.create(current_ruby_version.segments[0..1].join(".")) +is_ci = ENV.fetch("CI", "false").casecmp("true") == 0 -platform :mri do - # Debugging - Ensure ENV["DEBUG"] == "true" to use debuggers within spec suite - if ruby_version < Gem::Version.new("2.7") - # Use byebug in code - gem "byebug", ">= 11" - else - # Use binding.break, binding.b, or debugger in code - gem "debug", ">= 1.0.0" - end +gemspec - # Dev Console - Binding.pry - Irb replacement - gem "pry", "~> 0.14" # ruby >= 2.0 +### Debugging +if !is_ci && ENV.fetch("DEBUG", "false").casecmp("true") == 0 + platform :mri do + # Debugging - Ensure ENV["DEBUG"] == "true" to use debuggers within spec suite + if current_ruby_version < Gem::Version.new("2.7") + # Use byebug in code + gem "byebug", ">= 11" + # Dev Console - Binding.pry - Irb replacement + gem "pry", "~> 0.14" # ruby >= 2.0 + else + # Use binding.break, binding.b, or debugger in code + # eval_gemfile "gemfiles/modular/debug.gemfile" + end + end end -# This here to make sure appraisal2 works with Rails 3.0.0. -gem "thor", "~> 0.14.0" +if current_ruby_version < Gem::Version.new("1.9") + eval_gemfile("gemfiles/modular/ruby-1-8.gemfile") +elsif current_ruby_version < Gem::Version.new("2.0") + eval_gemfile("gemfiles/modular/ruby-1-9.gemfile") +elsif current_ruby_version < Gem::Version.new("2.1") + eval_gemfile("gemfiles/modular/ruby-2-0.gemfile") +elsif current_ruby_version < Gem::Version.new("2.2") + eval_gemfile("gemfiles/modular/ruby-2-1.gemfile") +elsif current_ruby_version < Gem::Version.new("2.3") + eval_gemfile("gemfiles/modular/ruby-2-2.gemfile") +elsif current_ruby_version < Gem::Version.new("2.4") + eval_gemfile("gemfiles/modular/ruby-2-3.gemfile") +elsif current_ruby_version < Gem::Version.new("2.5") + eval_gemfile("gemfiles/modular/ruby-2-4.gemfile") +elsif current_ruby_version < Gem::Version.new("2.6") + eval_gemfile("gemfiles/modular/ruby-2-5.gemfile") +elsif current_ruby_version < Gem::Version.new("2.7") + eval_gemfile("gemfiles/modular/ruby-2-6.gemfile") +elsif current_ruby_version < Gem::Version.new("3.0") + eval_gemfile("gemfiles/modular/ruby-2-7.gemfile") +elsif current_ruby_version < Gem::Version.new("3.1") + eval_gemfile("gemfiles/modular/ruby-3-0.gemfile") +elsif current_ruby_version < Gem::Version.new("3.2") + eval_gemfile("gemfiles/modular/ruby-3-1.gemfile") +elsif current_ruby_version < Gem::Version.new("3.3") + eval_gemfile("gemfiles/modular/ruby-3-2.gemfile") +elsif current_ruby_version < Gem::Version.new("3.4") + eval_gemfile("gemfiles/modular/ruby-3-3.gemfile") +elsif current_minor_ruby.eql?(latest_ruby_version) + # Only runs on the latest Ruby + eval_gemfile("gemfiles/modular/current.gemfile") -if ruby_version < Gem::Version.new("1.9") - eval File.read("Gemfile-1.8") -elsif ruby_version < Gem::Version.new("2.1") - eval File.read("Gemfile-2.0") -elsif ruby_version < Gem::Version.new("2.2") - eval File.read("Gemfile-2.1") -elsif ruby_version < Gem::Version.new("2.7") + if is_ci + if ENV.fetch("DEP_HEADS", "false").casecmp("true") == 0 + eval_gemfile("gemfiles/modular/dep_heads.gemfile") + elsif ENV.fetch("AUDIT_GEMS", "false").casecmp("true") == 0 + eval_gemfile("gemfiles/modular/audit.gemfile") + elsif ENV.fetch("COVERAGE_GEMS", "false").casecmp("true") == 0 + eval_gemfile("gemfiles/modular/coverage.gemfile") + elsif ENV.fetch("STYLE_GEMS", "false").casecmp("true") == 0 + eval_gemfile("gemfiles/modular/style.gemfile") + else + eval_gemfile("gemfiles/modular/current.gemfile") + end + else + ### Security Audit + eval_gemfile("gemfiles/modular/audit.gemfile") + ### Test Coverage + eval_gemfile("gemfiles/modular/coverage.gemfile") + ### Documentation + eval_gemfile("gemfiles/modular/documentation.gemfile") + ### Linting + eval_gemfile("gemfiles/modular/style.gemfile") + end +elsif current_minor_ruby > latest_ruby_version + eval_gemfile("gemfiles/modular/heads.gemfile") # Std Lib extractions gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 else - # Ruby >= 2.7 we can run style / lint checks via rubocop-gradual with rubocop-lts rules for Ruby 1.8+. - # This means we can develop on modern Ruby but remain compatible with ancient Ruby. - # TODO: Replace individual style gems below with modular gemfile, once eval_gemfile support is added to appraisal2. - # eval_gemfile "gemfiles/modular/style.gemfile" - # We run rubocop on the latest version of Ruby, - # but in support of the oldest supported version of Ruby - gem "rubocop-lts", "~> 0.1", ">= 0.1.1" # Style and Linting support for Ruby >= 1.8 - gem "rubocop-packaging", "~> 0.5", ">= 0.5.2" - gem "rubocop-rspec", "~> 3.2" - gem "standard", ">= 1.35.1", "!= 1.41.1", "!= 1.42.0" - - # Std Lib extractions - gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 + warn "Unhandled Ruby version: #{RUBY_VERSION}" end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..aedd265b --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,297 @@ +GIT + remote: https://github.com/dashingrocket/simplecov-cobertura + revision: b72eacdeab8b055533debc6fd150cb977db0ca3e + branch: main + specs: + simplecov-cobertura (2.1.1.pre.dev) + rexml + simplecov (~> 0.19) + +GIT + remote: https://github.com/pboling/yard-junk + revision: 54ccebabbfa9a9cd44d0b991687ebbfd22c32b55 + branch: next + specs: + yard-junk (0.0.10) + backports (>= 3.18) + benchmark + ostruct + rainbow + yard + +PATH + remote: . + specs: + appraisal2 (3.0.0) + bundler (>= 1.17.3) + rake (>= 10) + thor (>= 0.14) + +GEM + remote: https://rubygems.org/ + specs: + activesupport (8.0.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) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + ast (2.4.3) + backports (3.25.1) + base64 (0.3.0) + benchmark (0.4.1) + bigdecimal (3.2.2) + bundler-audit (0.9.2) + bundler (>= 1.2.0, < 3) + thor (~> 1.0) + concurrent-ruby (1.3.5) + connection_pool (2.5.3) + date (3.4.1) + diff-lcs (1.6.2) + diffy (3.4.4) + docile (1.4.1) + drb (2.2.3) + dry-configurable (1.3.0) + dry-core (~> 1.1) + zeitwerk (~> 2.6) + dry-core (1.1.0) + concurrent-ruby (~> 1.0) + logger + zeitwerk (~> 2.6) + dry-inflector (1.2.0) + dry-initializer (3.2.0) + dry-logic (1.6.0) + bigdecimal + concurrent-ruby (~> 1.0) + dry-core (~> 1.1) + zeitwerk (~> 2.6) + dry-schema (1.14.1) + concurrent-ruby (~> 1.0) + dry-configurable (~> 1.0, >= 1.0.1) + dry-core (~> 1.1) + dry-initializer (~> 3.2) + dry-logic (~> 1.5) + dry-types (~> 1.8) + zeitwerk (~> 2.6) + dry-types (1.8.3) + bigdecimal (~> 3.0) + concurrent-ruby (~> 1.0) + dry-core (~> 1.0) + dry-inflector (~> 1.0) + dry-logic (~> 1.4) + zeitwerk (~> 2.6) + erb (5.0.1) + i18n (1.14.7) + concurrent-ruby (~> 1.0) + json (2.12.2) + kramdown (2.5.1) + rexml (>= 3.3.9) + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + language_server-protocol (3.17.0.5) + lint_roller (1.1.0) + logger (1.7.0) + minitest (5.25.5) + nokogiri (1.18.8-aarch64-linux-gnu) + racc (~> 1.4) + nokogiri (1.18.8-aarch64-linux-musl) + racc (~> 1.4) + nokogiri (1.18.8-arm-linux-gnu) + racc (~> 1.4) + nokogiri (1.18.8-arm-linux-musl) + racc (~> 1.4) + nokogiri (1.18.8-arm64-darwin) + racc (~> 1.4) + nokogiri (1.18.8-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.18.8-x86_64-linux-gnu) + racc (~> 1.4) + nokogiri (1.18.8-x86_64-linux-musl) + racc (~> 1.4) + ostruct (0.6.2) + parallel (1.27.0) + parser (3.3.8.0) + ast (~> 2.4.1) + racc + prism (1.4.0) + psych (5.2.6) + date + stringio + racc (1.8.1) + rainbow (3.1.1) + rake (13.3.0) + rdoc (6.14.2) + erb + psych (>= 4.0.0) + reek (6.5.0) + dry-schema (~> 1.13) + logger (~> 1.6) + parser (~> 3.3.0) + rainbow (>= 2.0, < 4.0) + rexml (~> 3.1) + regexp_parser (2.10.0) + rexml (3.4.1) + rspec (3.13.1) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-block_is_expected (1.0.6) + rspec-core (3.13.5) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.5) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-pending_for (0.1.17) + rake (>= 10) + rspec-core (~> 3.0) + ruby_engine (~> 2.0) + ruby_version (~> 1.0) + rspec-support (3.13.4) + rubocop (1.75.8) + json (~> 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) + parallel (~> 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.44.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.45.1) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-gradual (0.3.6) + diff-lcs (>= 1.2.0, < 2.0) + diffy (~> 3.0) + parallel (~> 1.10) + rainbow (>= 2.2.2, < 4.0) + rubocop (~> 1.0) + rubocop-lts (0.1.1) + rubocop-ruby1_8 (>= 1.0.5, < 2) + standard-rubocop-lts (>= 1.0.3, < 3) + version_gem (>= 1.1.2, < 3) + rubocop-md (1.2.4) + rubocop (>= 1.45) + rubocop-minitest (0.38.1) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + rubocop-packaging (0.6.0) + lint_roller (~> 1.1.0) + rubocop (>= 1.72.1, < 2.0) + rubocop-performance (1.25.0) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + rubocop-rake (0.7.1) + lint_roller (~> 1.1) + rubocop (>= 1.72.1) + rubocop-rspec (3.6.0) + lint_roller (~> 1.1) + rubocop (~> 1.72, >= 1.72.1) + rubocop-ruby1_8 (1.0.7) + rubocop-gradual (~> 0.3, >= 0.3.1) + rubocop-md (~> 1.2) + rubocop-rake (~> 0.6) + rubocop-shopify (~> 2.14) + rubocop-thread_safety (~> 0.5, >= 0.5.1) + standard-rubocop-lts (~> 1.0, >= 1.0.7) + version_gem (>= 1.1.3, < 3) + rubocop-shopify (2.17.1) + rubocop (~> 1.62) + rubocop-thread_safety (0.7.3) + lint_roller (~> 1.1) + rubocop (~> 1.72, >= 1.72.1) + rubocop-ast (>= 1.44.0, < 2.0) + ruby-progressbar (1.13.0) + ruby_engine (2.0.3) + ruby_version (1.0.3) + securerandom (0.4.1) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.13.1) + simplecov_json_formatter (0.1.4) + standard (1.50.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.75.5) + standard-custom (~> 1.0.0) + standard-performance (~> 1.8) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.8.0) + lint_roller (~> 1.1) + rubocop-performance (~> 1.25.0) + standard-rubocop-lts (1.0.10) + rspec-block_is_expected (~> 1.0, >= 1.0.5) + standard (>= 1.35.1, < 2) + standard-custom (>= 1.0.2, < 2) + standard-performance (>= 1.3.1, < 2) + version_gem (>= 1.1.4, < 3) + stringio (3.1.7) + thor (1.3.2) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) + uri (1.0.3) + version_gem (1.1.8) + yard (0.9.37) + yard-relative_markdown_links (0.5.0) + nokogiri (>= 1.14.3, < 2) + zeitwerk (2.7.3) + +PLATFORMS + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + x86_64-darwin + x86_64-linux-gnu + x86_64-linux-musl + +DEPENDENCIES + activesupport (>= 3.2.21) + appraisal2! + benchmark (~> 0.4) + bundler-audit (~> 0.9.2) + kramdown (~> 2.5, >= 2.5.1) + kramdown-parser-gfm (~> 1.1) + logger (~> 1.7) + ostruct (~> 0.6, >= 0.6.1) + rdoc (~> 6.11) + reek (~> 6.4) + rspec (~> 3.13) + rspec-block_is_expected (~> 1.0, >= 1.0.6) + rspec-pending_for (~> 0.1, >= 0.1.17) + rubocop (~> 1.73, >= 1.73.2) + rubocop-lts (~> 0.1, >= 0.1.1) + rubocop-minitest (~> 0.36) + rubocop-packaging (~> 0.6, >= 0.6.0) + rubocop-rspec (~> 3.2) + simplecov-cobertura! + standard (~> 1.47) + thor (~> 1.3.2) + uri (~> 1.0, >= 1.0.3) + yard (~> 0.9, >= 0.9.37) + yard-junk (~> 0.0, >= 0.0.10)! + yard-relative_markdown_links (~> 0.5.0) + +BUNDLED WITH + 2.6.9 diff --git a/README.md b/README.md index 003e3bb3..55f9cecd 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ source "https://rubygems.org" gemspec -gem "appraisal" +gem "appraisal2" ``` Now when you need to update your appraisals: diff --git a/Rakefile b/Rakefile index 44f0463b..fc98ba26 100644 --- a/Rakefile +++ b/Rakefile @@ -1,23 +1,126 @@ -# frozen_string_literal: true - -require "bundler/setup" require "bundler/gem_tasks" -require "rspec/core/rake_task" +require "require_bench" if ENV.fetch("REQUIRE_BENCH", "false").casecmp("true") == 0 + +defaults = [] + +# See: https://docs.gitlab.com/ci/variables/predefined_variables/ +is_gitlab = ENV.fetch("GITLAB_CI", "false").casecmp("true") == 0 -RSpec::Core::RakeTask.new do |t| - t.pattern = "spec/**/*_spec.rb" - t.ruby_opts = %w[-w] - t.verbose = false +### DEVELOPMENT TASKS +# Setup Kettle Soup Cover +begin + require "kettle-soup-cover" + + Kettle::Soup::Cover.install_tasks + # NOTE: Coverage on CI is configured independent of this task. + # This task is for local development, as it opens results in browser + defaults << "coverage" unless Kettle::Soup::Cover::IS_CI +rescue LoadError + desc("(stub) coverage is unavailable") + task("coverage") do + warn("NOTE: kettle-soup-cover isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end end +# Setup Bundle Audit +begin + require "bundler/audit/task" + + Bundler::Audit::Task.new + defaults.push("bundle:audit:update", "bundle:audit") +rescue LoadError + desc("(stub) bundle:audit is unavailable") + task("bundle:audit") do + warn("NOTE: bundler-audit isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end + desc("(stub) bundle:audit:update is unavailable") + task("bundle:audit:update") do + warn("NOTE: bundler-audit isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +# Setup Tests +begin + require "rspec/core/rake_task" + + RSpec::Core::RakeTask.new(:spec) + defaults << "spec" +rescue LoadError + desc("spec task stub") + task(:spec) do + warn("NOTE: rspec isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +desc "run spec task with test task" +task :test => :spec + +# Setup RuboCop-LTS begin require "rubocop/lts" + Rubocop::Lts.install_tasks + # Make autocorrect the default rubocop task + defaults << "rubocop_gradual:autocorrect" rescue LoadError + desc("(stub) rubocop_gradual is unavailable") task(:rubocop_gradual) do - warn("RuboCop (Gradual) is disabled") + warn("NOTE: rubocop-lts isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +# Setup Yard +begin + require "yard" + + YARD::Rake::YardocTask.new(:yard) do |t| + t.files = [ + # Source Splats (alphabetical) + "lib/**/*.rb", + "-", # source and extra docs are separated by "-" + # Extra Files (alphabetical) + "*.cff", + "*.md", + "*.txt", + ] + t.stats_options = ["--list-undoc"] if ENV.fetch("VERBOSE", "false").casecmp("true") == 0 + end + defaults << "yard" +rescue LoadError + desc("(stub) yard is unavailable") + task(:yard) do + warn("NOTE: yard isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +# Setup Reek +begin + require "reek/rake/task" + + Reek::Rake::Task.new do |t| + t.fail_on_error = true + t.verbose = false + t.source_files = "{lib,test}/**/*.rb" + end + defaults << "reek" unless is_gitlab +rescue LoadError + desc("(stub) reek is unavailable") + task(:reek) do + warn("NOTE: reek isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +### RELEASE TASKS +# Setup stone_checksums +begin + require "stone_checksums" + + GemChecksums.install_tasks +rescue LoadError + desc("(stub) build:generate_checksums is unavailable") + task("build:generate_checksums") do + warn("NOTE: stone_checksums isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") end end -desc "Default: rubocop_gradual's autocorrect and run the rspec examples" -task :default => ["rubocop_gradual:autocorrect", :spec] +task :default => defaults diff --git a/appraisal2.gemspec b/appraisal2.gemspec index a9994e19..854a33a1 100644 --- a/appraisal2.gemspec +++ b/appraisal2.gemspec @@ -7,47 +7,63 @@ lib = File.expand_path("../lib", __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "appraisal/version" -Gem::Specification.new do |s| - s.name = "appraisal2" - s.version = Appraisal::VERSION.dup - s.platform = Gem::Platform::RUBY - s.authors = ["Joe Ferris", "Prem Sichanugrist"] - s.email = ["jferris@thoughtbot.com", "prem@thoughtbot.com"] - s.homepage = "http://github.com/appraisal-rb/appraisal2" - s.summary = "Find out what your Ruby gems are worth" - s.description = 'Appraisal integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."' - s.license = "MIT" +Gem::Specification.new do |spec| + spec.name = "appraisal2" + spec.version = Appraisal::VERSION.dup + spec.platform = Gem::Platform::RUBY + spec.authors = ["Joe Ferris", "Prem Sichanugrist"] + spec.email = ["jferris@thoughtbot.com", "prem@thoughtbot.com"] + spec.homepage = "http://github.com/appraisal-rb/appraisal2" + spec.summary = "Find out what your Ruby gems are worth" + spec.description = 'Appraisal integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."' + spec.license = "MIT" - # specify which files should be added to the gem when it is released. - s.files = Dir[ - # Splats (keep alphabetical) + # Specify which files are part of the released package. + spec.files = Dir[ + # Splats (alphabetical) "lib/**/*.rb", ] - - # automatically included with gem package, no need to list twice (i.e. do not list in files above). - s.extra_rdoc_files = Dir[ - # Files (keep alphabetical) + # Automatically included with gem package, no need to list again in files. + spec.extra_rdoc_files = Dir[ + # Files (alphabetical) + "CHANGELOG.md", + "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", - "MIT-LICENSE", + "LICENSE.txt", "README.md", "SECURITY.md", ] - + spec.rdoc_options += [ + "--title", + "#{spec.name} - #{spec.summary}", + "--main", + "CHANGELOG.md", + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.md", + "LICENSE.txt", + "README.md", + "SECURITY.md", + "--line-numbers", + "--inline-source", + "--quiet", + ] + spec.require_paths = ["lib"] # bin/ is scripts, in any available language, for development of this specific gem # exe/ is for ruby scripts that will ship with this gem to be used by other tools - s.bindir = "exe" + spec.bindir = "exe" # files listed are relative paths from bindir above. - s.executables = [ + spec.executables = [ "appraisal", ] - s.required_ruby_version = ">= 1.8.7" + spec.required_ruby_version = ">= 1.8.7" - s.add_runtime_dependency("bundler", ">= 1.17.3") # Last version supporting Ruby 1.8.7 - s.add_runtime_dependency("rake", ">= 10") # Last version supporting Ruby 1.8.7 - s.add_runtime_dependency("thor", ">= 0.14") # Last version supporting Ruby 1.8.7 && Rails 3 + spec.add_dependency("bundler", ">= 1.17.3") # Last version supporting Ruby 1.8.7 + spec.add_dependency("rake", ">= 10") # Last version supporting Ruby 1.8.7 + spec.add_dependency("thor", ">= 0.14") # Last version supporting Ruby 1.8.7 && Rails 3 - s.add_development_dependency("activesupport", ">= 3.2.21") - s.add_development_dependency("rspec", "~> 3.13") - s.add_development_dependency("rspec-pending_for", "~> 0.1", ">= 0.1.17") + spec.add_development_dependency("activesupport", ">= 3.2.21") + spec.add_development_dependency("rspec", "~> 3.13") + spec.add_development_dependency("rspec-block_is_expected", "~> 1.0", ">= 1.0.6") + spec.add_development_dependency("rspec-pending_for", "~> 0.1", ">= 0.1.17") end diff --git a/bin/appraisal b/bin/appraisal new file mode 100755 index 00000000..ab11700a --- /dev/null +++ b/bin/appraisal @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'appraisal' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("appraisal2", "appraisal") diff --git a/bin/bundle-audit b/bin/bundle-audit new file mode 100755 index 00000000..a0e7ba0e --- /dev/null +++ b/bin/bundle-audit @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'bundle-audit' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("bundler-audit", "bundle-audit") diff --git a/bin/bundler-audit b/bin/bundler-audit new file mode 100755 index 00000000..334a7378 --- /dev/null +++ b/bin/bundler-audit @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'bundler-audit' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("bundler-audit", "bundler-audit") diff --git a/bin/code_climate_reek b/bin/code_climate_reek new file mode 100755 index 00000000..afe0d79f --- /dev/null +++ b/bin/code_climate_reek @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'code_climate_reek' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("reek", "code_climate_reek") diff --git a/bin/coderay b/bin/coderay new file mode 100755 index 00000000..b13b22e9 --- /dev/null +++ b/bin/coderay @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'coderay' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("coderay", "coderay") diff --git a/bin/erb b/bin/erb new file mode 100755 index 00000000..59d3df9d --- /dev/null +++ b/bin/erb @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'erb' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("erb", "erb") diff --git a/bin/htmldiff b/bin/htmldiff new file mode 100755 index 00000000..0aeaec87 --- /dev/null +++ b/bin/htmldiff @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'htmldiff' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("diff-lcs", "htmldiff") diff --git a/bin/irb b/bin/irb new file mode 100755 index 00000000..e7de6d6c --- /dev/null +++ b/bin/irb @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'irb' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("irb", "irb") diff --git a/bin/kramdown b/bin/kramdown new file mode 100755 index 00000000..2da4ffe3 --- /dev/null +++ b/bin/kramdown @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kramdown' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("kramdown", "kramdown") diff --git a/bin/ldiff b/bin/ldiff new file mode 100755 index 00000000..8173edec --- /dev/null +++ b/bin/ldiff @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'ldiff' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("diff-lcs", "ldiff") diff --git a/bin/nokogiri b/bin/nokogiri new file mode 100755 index 00000000..c00ec262 --- /dev/null +++ b/bin/nokogiri @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'nokogiri' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("nokogiri", "nokogiri") diff --git a/bin/pry b/bin/pry new file mode 100755 index 00000000..eb530525 --- /dev/null +++ b/bin/pry @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'pry' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("pry", "pry") diff --git a/bin/racc b/bin/racc new file mode 100755 index 00000000..81900158 --- /dev/null +++ b/bin/racc @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'racc' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("racc", "racc") diff --git a/bin/rake b/bin/rake new file mode 100755 index 00000000..4eb7d7bf --- /dev/null +++ b/bin/rake @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rake' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rake", "rake") diff --git a/bin/rake2thor b/bin/rake2thor new file mode 100755 index 00000000..4588cdc9 --- /dev/null +++ b/bin/rake2thor @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rake2thor' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("thor", "rake2thor") diff --git a/bin/rdbg b/bin/rdbg new file mode 100755 index 00000000..5e3b279f --- /dev/null +++ b/bin/rdbg @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rdbg' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("debug", "rdbg") diff --git a/bin/rdoc b/bin/rdoc new file mode 100755 index 00000000..d2b6bcf8 --- /dev/null +++ b/bin/rdoc @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rdoc' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rdoc", "rdoc") diff --git a/bin/reek b/bin/reek new file mode 100755 index 00000000..2ec45920 --- /dev/null +++ b/bin/reek @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'reek' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("reek", "reek") diff --git a/bin/ri b/bin/ri new file mode 100755 index 00000000..72e25813 --- /dev/null +++ b/bin/ri @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'ri' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rdoc", "ri") diff --git a/bin/rubocop b/bin/rubocop new file mode 100755 index 00000000..369a05be --- /dev/null +++ b/bin/rubocop @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rubocop' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rubocop", "rubocop") diff --git a/bin/rubocop-gradual b/bin/rubocop-gradual new file mode 100755 index 00000000..07520055 --- /dev/null +++ b/bin/rubocop-gradual @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rubocop-gradual' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rubocop-gradual", "rubocop-gradual") diff --git a/bin/ruby-parse b/bin/ruby-parse new file mode 100755 index 00000000..d8ebc68d --- /dev/null +++ b/bin/ruby-parse @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'ruby-parse' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("parser", "ruby-parse") diff --git a/bin/ruby-rewrite b/bin/ruby-rewrite new file mode 100755 index 00000000..b4574aba --- /dev/null +++ b/bin/ruby-rewrite @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'ruby-rewrite' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("parser", "ruby-rewrite") diff --git a/bin/standardrb b/bin/standardrb new file mode 100755 index 00000000..b329561c --- /dev/null +++ b/bin/standardrb @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'standardrb' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("standard", "standardrb") diff --git a/bin/thor b/bin/thor new file mode 100755 index 00000000..ec401151 --- /dev/null +++ b/bin/thor @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'thor' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("thor", "thor") diff --git a/bin/yard b/bin/yard new file mode 100755 index 00000000..ea9daf5f --- /dev/null +++ b/bin/yard @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'yard' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("yard", "yard") diff --git a/bin/yard-junk b/bin/yard-junk new file mode 100755 index 00000000..be420a5c --- /dev/null +++ b/bin/yard-junk @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'yard-junk' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("yard-junk", "yard-junk") diff --git a/bin/yardoc b/bin/yardoc new file mode 100755 index 00000000..e1324dc1 --- /dev/null +++ b/bin/yardoc @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'yardoc' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("yard", "yardoc") diff --git a/bin/yri b/bin/yri new file mode 100755 index 00000000..f968fde1 --- /dev/null +++ b/bin/yri @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'yri' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("yard", "yri") diff --git a/exe/appraisal b/exe/appraisal index 16e4087a..7e1f3fce 100755 --- a/exe/appraisal +++ b/exe/appraisal @@ -3,7 +3,7 @@ require "rubygems" require "bundler/setup" -require "appraisal" +require "appraisal2" require "appraisal/cli" begin diff --git a/gemfiles/audit.gemfile b/gemfiles/audit.gemfile new file mode 100644 index 00000000..3f60bc8d --- /dev/null +++ b/gemfiles/audit.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/audit.gemfile") diff --git a/gemfiles/coverage.gemfile b/gemfiles/coverage.gemfile new file mode 100644 index 00000000..d7c27c45 --- /dev/null +++ b/gemfiles/coverage.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/coverage.gemfile") diff --git a/gemfiles/current.gemfile b/gemfiles/current.gemfile new file mode 100644 index 00000000..2584f3b7 --- /dev/null +++ b/gemfiles/current.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/current.gemfile") diff --git a/gemfiles/dep_heads.gemfile b/gemfiles/dep_heads.gemfile new file mode 100644 index 00000000..43e43e8b --- /dev/null +++ b/gemfiles/dep_heads.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/runtime_heads.gemfile") diff --git a/gemfiles/heads.gemfile b/gemfiles/heads.gemfile new file mode 100644 index 00000000..7b0f61a1 --- /dev/null +++ b/gemfiles/heads.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/heads.gemfile") diff --git a/gemfiles/modular/audit.gemfile b/gemfiles/modular/audit.gemfile new file mode 100644 index 00000000..e5cc9199 --- /dev/null +++ b/gemfiles/modular/audit.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Many gems are dropping support for Ruby < 3, +# so we only want to run our security audit in CI on Ruby 3+ +gem "bundler-audit", "~> 0.9.2" diff --git a/gemfiles/modular/coverage.gemfile b/gemfiles/modular/coverage.gemfile new file mode 100644 index 00000000..6a20ab1a --- /dev/null +++ b/gemfiles/modular/coverage.gemfile @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +# We run code coverage on the latest version of Ruby only. + +# Coverage +# All coverage gems are listed in gemspec dependencies. +# But fix in the main branch (https://github.com/dashingrocket/simplecov-cobertura/pull/32) +# needed to prevent the circular require warning and stacktrace. +gem "simplecov-cobertura", :github => "dashingrocket/simplecov-cobertura", :branch => "main" + +gem "ostruct", "~> 0.6", ">= 0.6.1" # Ruby >= 2.5 diff --git a/gemfiles/modular/current.gemfile b/gemfiles/modular/current.gemfile new file mode 100644 index 00000000..e08492a4 --- /dev/null +++ b/gemfiles/modular/current.gemfile @@ -0,0 +1,3 @@ +eval_gemfile("thor/r3/v1.3.gemfile") + +eval_gemfile("x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/modular/debug.gemfile b/gemfiles/modular/debug.gemfile new file mode 100644 index 00000000..9ba81787 --- /dev/null +++ b/gemfiles/modular/debug.gemfile @@ -0,0 +1,8 @@ +# Ex-Standard Library gems +gem "irb", "~> 1.15", ">= 1.15.2" # removed from stdlib in 3.5 + +platform :mri do + # Debugging + # Use binding.break, binding.b, or debugger in code + gem "debug", "~> 1.11" +end diff --git a/gemfiles/modular/documentation.gemfile b/gemfiles/modular/documentation.gemfile new file mode 100755 index 00000000..7c5c2e92 --- /dev/null +++ b/gemfiles/modular/documentation.gemfile @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +# Documentation +gem "kramdown", "~> 2.5", ">= 2.5.1" # Ruby >= 2.5 +gem "kramdown-parser-gfm", "~> 1.1" # Ruby >= 2.3 +gem "yard", "~> 0.9", ">= 0.9.37", :require => false +gem "yard-junk", "~> 0.0", ">= 0.0.10", :github => "pboling/yard-junk", :branch => "next", :require => false +gem "yard-relative_markdown_links", "~> 0.5.0" + +# Std Lib extractions +gem "rdoc", "~> 6.11" diff --git a/gemfiles/modular/heads.gemfile b/gemfiles/modular/heads.gemfile new file mode 100644 index 00000000..8e9b8f90 --- /dev/null +++ b/gemfiles/modular/heads.gemfile @@ -0,0 +1 @@ +# frozen_string_literal: true diff --git a/gemfiles/modular/logger/r2/v1.5.gemfile b/gemfiles/modular/logger/r2/v1.5.gemfile new file mode 100644 index 00000000..c4fc65e0 --- /dev/null +++ b/gemfiles/modular/logger/r2/v1.5.gemfile @@ -0,0 +1,3 @@ +# Ruby >= 2.3.0 +# Last version compatible with Ruby 2.4 +gem "logger", ">= 1.5.3", "< 2" diff --git a/gemfiles/modular/logger/r3/v1.7.gemfile b/gemfiles/modular/logger/r3/v1.7.gemfile new file mode 100644 index 00000000..f68bea9b --- /dev/null +++ b/gemfiles/modular/logger/r3/v1.7.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5.0 +gem "logger", "~> 1.7" diff --git a/gemfiles/modular/logger/vHEAD.gemfile b/gemfiles/modular/logger/vHEAD.gemfile new file mode 100644 index 00000000..0de4c020 --- /dev/null +++ b/gemfiles/modular/logger/vHEAD.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5 (dependency of omniauth) +gem "logger", :github => "ruby/logger", :branch => "master" diff --git a/gemfiles/modular/ruby_1_8.gemfile b/gemfiles/modular/ruby_1_8.gemfile new file mode 100644 index 00000000..d8d82ddc --- /dev/null +++ b/gemfiles/modular/ruby_1_8.gemfile @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +gem "i18n", "~> 0.6.0" +gem "activesupport", "~> 3.2.21" +gem "rake", "~> 10.5" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.3" + +eval_gemfile("thor/r1/v0.20.gemfile") + +eval_gemfile("x_std_libs/r1/libs.gemfile") diff --git a/gemfiles/modular/ruby_1_9.gemfile b/gemfiles/modular/ruby_1_9.gemfile new file mode 100644 index 00000000..98642542 --- /dev/null +++ b/gemfiles/modular/ruby_1_9.gemfile @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +gem "activesupport", "~> 4.2.7" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.3" + +eval_gemfile("thor/r1/v0.20.gemfile") + +eval_gemfile("x_std_libs/r1/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_0.gemfile b/gemfiles/modular/ruby_2_0.gemfile new file mode 100644 index 00000000..868eba7b --- /dev/null +++ b/gemfiles/modular/ruby_2_0.gemfile @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +gem "activesupport", "~> 4.2.7" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.3" + +eval_gemfile("thor/r2/v1.2.gemfile") + +eval_gemfile("x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_1.gemfile b/gemfiles/modular/ruby_2_1.gemfile new file mode 100644 index 00000000..831a33ee --- /dev/null +++ b/gemfiles/modular/ruby_2_1.gemfile @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +gem "activesupport", "~> 4.2.7" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.4" + +eval_gemfile("thor/r2/v1.2.gemfile") + +eval_gemfile("x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_2.gemfile b/gemfiles/modular/ruby_2_2.gemfile new file mode 100644 index 00000000..d2623b52 --- /dev/null +++ b/gemfiles/modular/ruby_2_2.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r2/v1.2.gemfile") + +eval_gemfile("x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_3.gemfile b/gemfiles/modular/ruby_2_3.gemfile new file mode 100644 index 00000000..d2623b52 --- /dev/null +++ b/gemfiles/modular/ruby_2_3.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r2/v1.2.gemfile") + +eval_gemfile("x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_4.gemfile b/gemfiles/modular/ruby_2_4.gemfile new file mode 100644 index 00000000..d2623b52 --- /dev/null +++ b/gemfiles/modular/ruby_2_4.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r2/v1.2.gemfile") + +eval_gemfile("x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_5.gemfile b/gemfiles/modular/ruby_2_5.gemfile new file mode 100644 index 00000000..d2623b52 --- /dev/null +++ b/gemfiles/modular/ruby_2_5.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r2/v1.2.gemfile") + +eval_gemfile("x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_6.gemfile b/gemfiles/modular/ruby_2_6.gemfile new file mode 100644 index 00000000..1dc52778 --- /dev/null +++ b/gemfiles/modular/ruby_2_6.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r2.6/v1.3.gemfile") + +eval_gemfile("x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_7.gemfile b/gemfiles/modular/ruby_2_7.gemfile new file mode 100644 index 00000000..1dc52778 --- /dev/null +++ b/gemfiles/modular/ruby_2_7.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r2.6/v1.3.gemfile") + +eval_gemfile("x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/modular/ruby_3_0.gemfile b/gemfiles/modular/ruby_3_0.gemfile new file mode 100644 index 00000000..132119d9 --- /dev/null +++ b/gemfiles/modular/ruby_3_0.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r3/v1.3.gemfile") + +eval_gemfile("x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/modular/ruby_3_1.gemfile b/gemfiles/modular/ruby_3_1.gemfile new file mode 100644 index 00000000..132119d9 --- /dev/null +++ b/gemfiles/modular/ruby_3_1.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r3/v1.3.gemfile") + +eval_gemfile("x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/modular/ruby_3_2.gemfile b/gemfiles/modular/ruby_3_2.gemfile new file mode 100644 index 00000000..132119d9 --- /dev/null +++ b/gemfiles/modular/ruby_3_2.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r3/v1.3.gemfile") + +eval_gemfile("x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/modular/ruby_3_3.gemfile b/gemfiles/modular/ruby_3_3.gemfile new file mode 100644 index 00000000..132119d9 --- /dev/null +++ b/gemfiles/modular/ruby_3_3.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +eval_gemfile("thor/r3/v1.3.gemfile") + +eval_gemfile("x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/modular/runtime_heads.gemfile b/gemfiles/modular/runtime_heads.gemfile new file mode 100644 index 00000000..eebb6ec6 --- /dev/null +++ b/gemfiles/modular/runtime_heads.gemfile @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# Test against HEAD of runtime dependencies so we can proactively file bugs + +# std lib extractions +eval_gemfile("x_std_libs/vHEAD.gemfile") + +# Runtime deps +eval_gemfile("thor/vHEAD.gemfile") diff --git a/gemfiles/modular/style.gemfile b/gemfiles/modular/style.gemfile index c9cf8473..50a340e2 100644 --- a/gemfiles/modular/style.gemfile +++ b/gemfiles/modular/style.gemfile @@ -3,10 +3,13 @@ # We run rubocop on the latest version of Ruby, # but in support of the oldest supported version of Ruby +gem "reek", "~> 6.4" +gem "rubocop", "~> 1.73", ">= 1.73.2" gem "rubocop-lts", "~> 0.1", ">= 0.1.1" # Style and Linting support for Ruby >= 1.8 -gem "rubocop-packaging", "~> 0.5", ">= 0.5.2" +gem "rubocop-minitest", "~> 0.36" +gem "rubocop-packaging", "~> 0.6", ">= 0.6.0" # Ruby >= 2.7 gem "rubocop-rspec", "~> 3.2" -gem "standard", ">= 1.35.1", "!= 1.41.1", "!= 1.42.0" +gem "standard", "~> 1.47" # Std Lib extractions gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 diff --git a/gemfiles/modular/thor/r1/v0.20.gemfile b/gemfiles/modular/thor/r1/v0.20.gemfile new file mode 100644 index 00000000..3bf4c31a --- /dev/null +++ b/gemfiles/modular/thor/r1/v0.20.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 1.8.7, last compatible with Ruby 1.9 (dependency of rails) +gem "thor", "~> 0.20.3" diff --git a/gemfiles/modular/thor/r2.6/v1.3.gemfile b/gemfiles/modular/thor/r2.6/v1.3.gemfile new file mode 100644 index 00000000..4ef8127f --- /dev/null +++ b/gemfiles/modular/thor/r2.6/v1.3.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.6 (dependency of rails) +gem "thor", "~> 1.3.2" \ No newline at end of file diff --git a/gemfiles/modular/thor/r2/v1.2.gemfile b/gemfiles/modular/thor/r2/v1.2.gemfile new file mode 100644 index 00000000..959f5bfe --- /dev/null +++ b/gemfiles/modular/thor/r2/v1.2.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.0, last compatible with Ruby 2.5 (dependency of rails) +gem "thor", "~> 1.2.2" diff --git a/gemfiles/modular/thor/r3/v1.3.gemfile b/gemfiles/modular/thor/r3/v1.3.gemfile new file mode 100644 index 00000000..4ef8127f --- /dev/null +++ b/gemfiles/modular/thor/r3/v1.3.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.6 (dependency of rails) +gem "thor", "~> 1.3.2" \ No newline at end of file diff --git a/gemfiles/modular/thor/vHEAD.gemfile b/gemfiles/modular/thor/vHEAD.gemfile new file mode 100644 index 00000000..cd40549a --- /dev/null +++ b/gemfiles/modular/thor/vHEAD.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.6 (dependency of rails) +gem "thor", :github => "rails/thor", :branch => "main" diff --git a/gemfiles/modular/uri/r2/v0.gemfile b/gemfiles/modular/uri/r2/v0.gemfile new file mode 100644 index 00000000..939c0528 --- /dev/null +++ b/gemfiles/modular/uri/r2/v0.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5.0 +gem "uri", "~> 0.13", ">= 0.13.2" diff --git a/gemfiles/modular/uri/r3/v1.gemfile b/gemfiles/modular/uri/r3/v1.gemfile new file mode 100644 index 00000000..0878d80e --- /dev/null +++ b/gemfiles/modular/uri/r3/v1.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5.0 +gem "uri", "~> 1.0", ">= 1.0.3" diff --git a/gemfiles/modular/uri/vHEAD.gemfile b/gemfiles/modular/uri/vHEAD.gemfile new file mode 100644 index 00000000..e376993a --- /dev/null +++ b/gemfiles/modular/uri/vHEAD.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5 +gem "uri", :github => "ruby/uri", :branch => "master" diff --git a/gemfiles/modular/x_std_libs/r1/libs.gemfile b/gemfiles/modular/x_std_libs/r1/libs.gemfile new file mode 100644 index 00000000..4313604c --- /dev/null +++ b/gemfiles/modular/x_std_libs/r1/libs.gemfile @@ -0,0 +1,2 @@ +eval_gemfile "../../logger/r2/v1.5.gemfile" +eval_gemfile "../../uri/r2/v0.gemfile" diff --git a/gemfiles/modular/x_std_libs/r2/libs.gemfile b/gemfiles/modular/x_std_libs/r2/libs.gemfile new file mode 100644 index 00000000..4313604c --- /dev/null +++ b/gemfiles/modular/x_std_libs/r2/libs.gemfile @@ -0,0 +1,2 @@ +eval_gemfile "../../logger/r2/v1.5.gemfile" +eval_gemfile "../../uri/r2/v0.gemfile" diff --git a/gemfiles/modular/x_std_libs/r3/libs.gemfile b/gemfiles/modular/x_std_libs/r3/libs.gemfile new file mode 100644 index 00000000..41651c40 --- /dev/null +++ b/gemfiles/modular/x_std_libs/r3/libs.gemfile @@ -0,0 +1,2 @@ +eval_gemfile "../../logger/r3/v1.7.gemfile" +eval_gemfile "../../uri/r3/v1.gemfile" diff --git a/gemfiles/modular/x_std_libs/vHEAD.gemfile b/gemfiles/modular/x_std_libs/vHEAD.gemfile new file mode 100644 index 00000000..8992c90c --- /dev/null +++ b/gemfiles/modular/x_std_libs/vHEAD.gemfile @@ -0,0 +1,2 @@ +eval_gemfile "../logger/vHEAD.gemfile" +eval_gemfile "../uri/vHEAD.gemfile" diff --git a/gemfiles/ruby_1_8.gemfile b/gemfiles/ruby_1_8.gemfile new file mode 100644 index 00000000..1a68db93 --- /dev/null +++ b/gemfiles/ruby_1_8.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_1_8.gemfile") diff --git a/gemfiles/ruby_1_9.gemfile b/gemfiles/ruby_1_9.gemfile new file mode 100644 index 00000000..21b899ba --- /dev/null +++ b/gemfiles/ruby_1_9.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_1_9.gemfile") diff --git a/gemfiles/ruby_2_0.gemfile b/gemfiles/ruby_2_0.gemfile new file mode 100644 index 00000000..e7d71981 --- /dev/null +++ b/gemfiles/ruby_2_0.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_2_0.gemfile") diff --git a/gemfiles/ruby_2_1.gemfile b/gemfiles/ruby_2_1.gemfile new file mode 100644 index 00000000..0fd4cd5e --- /dev/null +++ b/gemfiles/ruby_2_1.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_2_1.gemfile") diff --git a/gemfiles/ruby_2_2.gemfile b/gemfiles/ruby_2_2.gemfile new file mode 100644 index 00000000..5e461ad7 --- /dev/null +++ b/gemfiles/ruby_2_2.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_2_2.gemfile") diff --git a/gemfiles/ruby_2_3.gemfile b/gemfiles/ruby_2_3.gemfile new file mode 100644 index 00000000..80288f99 --- /dev/null +++ b/gemfiles/ruby_2_3.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_2_3.gemfile") diff --git a/gemfiles/ruby_2_4.gemfile b/gemfiles/ruby_2_4.gemfile new file mode 100644 index 00000000..eedc28f8 --- /dev/null +++ b/gemfiles/ruby_2_4.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_2_4.gemfile") diff --git a/gemfiles/ruby_2_5.gemfile b/gemfiles/ruby_2_5.gemfile new file mode 100644 index 00000000..2fd2850b --- /dev/null +++ b/gemfiles/ruby_2_5.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_2_5.gemfile") diff --git a/gemfiles/ruby_2_6.gemfile b/gemfiles/ruby_2_6.gemfile new file mode 100644 index 00000000..3cfe2030 --- /dev/null +++ b/gemfiles/ruby_2_6.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_2_6.gemfile") diff --git a/gemfiles/ruby_2_7.gemfile b/gemfiles/ruby_2_7.gemfile new file mode 100644 index 00000000..f2a5af4e --- /dev/null +++ b/gemfiles/ruby_2_7.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_2_7.gemfile") diff --git a/gemfiles/ruby_3_0.gemfile b/gemfiles/ruby_3_0.gemfile new file mode 100644 index 00000000..a5b6b8c4 --- /dev/null +++ b/gemfiles/ruby_3_0.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_3_0.gemfile") diff --git a/gemfiles/ruby_3_1.gemfile b/gemfiles/ruby_3_1.gemfile new file mode 100644 index 00000000..9c71da06 --- /dev/null +++ b/gemfiles/ruby_3_1.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_3_1.gemfile") diff --git a/gemfiles/ruby_3_2.gemfile b/gemfiles/ruby_3_2.gemfile new file mode 100644 index 00000000..0c560ead --- /dev/null +++ b/gemfiles/ruby_3_2.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_3_2.gemfile") diff --git a/gemfiles/ruby_3_3.gemfile b/gemfiles/ruby_3_3.gemfile new file mode 100644 index 00000000..7ef4eb07 --- /dev/null +++ b/gemfiles/ruby_3_3.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/ruby_3_3.gemfile") diff --git a/gemfiles/style.gemfile b/gemfiles/style.gemfile new file mode 100644 index 00000000..6b11699b --- /dev/null +++ b/gemfiles/style.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec :path => "../" + +eval_gemfile("modular/style.gemfile") diff --git a/lib/appraisal/appraisal.rb b/lib/appraisal/appraisal.rb index ccbed470..23aa1d8a 100644 --- a/lib/appraisal/appraisal.rb +++ b/lib/appraisal/appraisal.rb @@ -1,11 +1,14 @@ # frozen_string_literal: true +# Std Lib +require "fileutils" +require "pathname" + +# This gem require "appraisal/gemfile" require "appraisal/command" require "appraisal/customize" require "appraisal/utils" -require "fileutils" -require "pathname" module Appraisal # Represents one appraisal and its dependencies diff --git a/lib/appraisal/cli.rb b/lib/appraisal/cli.rb index f5a966a2..e6f6a4b0 100644 --- a/lib/appraisal/cli.rb +++ b/lib/appraisal/cli.rb @@ -108,7 +108,7 @@ def list desc "version", "Display the version and exit" def version - puts "Appraisal #{VERSION}" + puts "Appraisal2 #{VERSION}" end private diff --git a/lib/appraisal/dependency_list.rb b/lib/appraisal/dependency_list.rb index 8a42c938..0e4af1a2 100644 --- a/lib/appraisal/dependency_list.rb +++ b/lib/appraisal/dependency_list.rb @@ -1,8 +1,11 @@ # frozen_string_literal: true +# Std libs +require "set" + +# This gem require "appraisal/dependency" require "appraisal/ordered_hash" -require "set" module Appraisal class DependencyList diff --git a/lib/appraisal/version.rb b/lib/appraisal/version.rb index 38a986c5..e917bd31 100644 --- a/lib/appraisal/version.rb +++ b/lib/appraisal/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Appraisal - VERSION = "3.0.0.rc1" + VERSION = "3.0.0" end diff --git a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb index 23c07f68..812f5e04 100644 --- a/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb +++ b/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb @@ -100,7 +100,7 @@ APPRAISALS run "bundle install --local" - run "appraisal generate" + run "bundle exec appraisal generate" expect(content_of("gemfiles/breakfast.gemfile")).to eq <<-GEMFILE.strip_heredoc.rstrip # This file was generated by Appraisal diff --git a/spec/acceptance/bundle_with_custom_path_spec.rb b/spec/acceptance/bundle_with_custom_path_spec.rb index 7cb1a67b..f5fe0f5d 100644 --- a/spec/acceptance/bundle_with_custom_path_spec.rb +++ b/spec/acceptance/bundle_with_custom_path_spec.rb @@ -12,9 +12,9 @@ gem 'appraisal2', :path => #{PROJECT_ROOT.inspect} if RUBY_VERSION < "1.9" - #{File.read(File.join(PROJECT_ROOT, "Gemfile-1.8"))} + #{File.read(File.join(PROJECT_ROOT, "spec", "fixtures", "Gemfile-1.8"))} elsif RUBY_VERSION < "2.2" - #{File.read(File.join(PROJECT_ROOT, "Gemfile-2.1"))} + #{File.read(File.join(PROJECT_ROOT, "spec", "fixtures", "Gemfile-2.1"))} end GEMFILE @@ -43,7 +43,7 @@ end end - include_examples "gemfile dependencies are satisfied" + it_behaves_like "gemfile dependencies are satisfied" context "when already installed in vendor/another" do before do @@ -62,6 +62,6 @@ run "bundle config unset --local path" end - include_examples "gemfile dependencies are satisfied" + it_behaves_like "gemfile dependencies are satisfied" end end diff --git a/spec/acceptance/cli/version_spec.rb b/spec/acceptance/cli/version_spec.rb index ab313df9..4a82b34b 100644 --- a/spec/acceptance/cli/version_spec.rb +++ b/spec/acceptance/cli/version_spec.rb @@ -5,7 +5,7 @@ it "prints out version string" do output = run "appraisal version" - expect(output).to include("Appraisal #{Appraisal::VERSION}") + expect(output).to include("Appraisal2 #{Appraisal::VERSION}") end end @@ -13,7 +13,7 @@ it "prints out version string" do output = run "appraisal -v" - expect(output).to include("Appraisal #{Appraisal::VERSION}") + expect(output).to include("Appraisal2 #{Appraisal::VERSION}") end end @@ -21,7 +21,7 @@ it "prints out version string" do output = run "appraisal --version" - expect(output).to include("Appraisal #{Appraisal::VERSION}") + expect(output).to include("Appraisal2 #{Appraisal::VERSION}") end end end diff --git a/spec/acceptance/eval_gemfile_spec.rb b/spec/acceptance/eval_gemfile_spec.rb index d23ce98d..b6fcddbf 100644 --- a/spec/acceptance/eval_gemfile_spec.rb +++ b/spec/acceptance/eval_gemfile_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "spec_helper" - RSpec.describe "eval_gemfile" do before do build_appraisal_file diff --git a/spec/appraisal/appraisal_file_spec.rb b/spec/appraisal/appraisal_file_spec.rb index c90a390a..b5568e43 100644 --- a/spec/appraisal/appraisal_file_spec.rb +++ b/spec/appraisal/appraisal_file_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "spec_helper" require "appraisal/appraisal_file" # Requiring this to make the test pass on Rubinius 2.2.5 @@ -10,7 +9,7 @@ RSpec.describe Appraisal::AppraisalFile do it "complains when no Appraisals file is found" do - allow(File).to receive(:exist?).with(/Gemfile/).and_return(true) + allow(File).to receive(:exist?).with(/gemfile/i).and_return(true) allow(File).to receive(:exist?).with("Appraisals").and_return(false) expect { described_class.new }.to raise_error(Appraisal::AppraisalsNotFound) end diff --git a/spec/appraisal/appraisal_spec.rb b/spec/appraisal/appraisal_spec.rb index 4a694411..c286732b 100644 --- a/spec/appraisal/appraisal_spec.rb +++ b/spec/appraisal/appraisal_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "spec_helper" require "appraisal/appraisal" require "tempfile" diff --git a/spec/appraisal/customize_spec.rb b/spec/appraisal/customize_spec.rb index d833f8c4..50fb4f58 100644 --- a/spec/appraisal/customize_spec.rb +++ b/spec/appraisal/customize_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "spec_helper" require "appraisal/appraisal" require "appraisal/customize" diff --git a/spec/appraisal/dependency_list_spec.rb b/spec/appraisal/dependency_list_spec.rb index a9fac337..e0e40200 100644 --- a/spec/appraisal/dependency_list_spec.rb +++ b/spec/appraisal/dependency_list_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "spec_helper" require "appraisal/dependency_list" RSpec.describe Appraisal::DependencyList do diff --git a/spec/appraisal/gemfile_spec.rb b/spec/appraisal/gemfile_spec.rb index 07c02f6f..e9e65957 100644 --- a/spec/appraisal/gemfile_spec.rb +++ b/spec/appraisal/gemfile_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "spec_helper" require "appraisal/gemfile" require "active_support/core_ext/string/strip" diff --git a/spec/appraisal/utils_spec.rb b/spec/appraisal/utils_spec.rb index 743f8683..0d522940 100644 --- a/spec/appraisal/utils_spec.rb +++ b/spec/appraisal/utils_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "spec_helper" require "appraisal/utils" RSpec.describe Appraisal::Utils do diff --git a/spec/config/byebug.rb b/spec/config/byebug.rb new file mode 100644 index 00000000..164f9830 --- /dev/null +++ b/spec/config/byebug.rb @@ -0,0 +1,11 @@ +if ENV["CI"].nil? && ENV.fetch("DEBUG", "false").casecmp("true") == 0 + ENV["VERBOSE"] = "true" + ruby_version = Gem::Version.new(RUBY_VERSION) + if ruby_version < Gem::Version.new("2.7") + # Use byebug in code + require "byebug" + else + # Use binding.break, binding.b, or debugger in code + require "debug" + end +end diff --git a/spec/config/rspec/rspec_block_is_expected.rb b/spec/config/rspec/rspec_block_is_expected.rb new file mode 100644 index 00000000..ab140fa4 --- /dev/null +++ b/spec/config/rspec/rspec_block_is_expected.rb @@ -0,0 +1,2 @@ +require "rspec/block_is_expected" +require "rspec/block_is_expected/matchers/not" diff --git a/spec/config/rspec/rspec_core.rb b/spec/config/rspec/rspec_core.rb new file mode 100644 index 00000000..46ceaa81 --- /dev/null +++ b/spec/config/rspec/rspec_core.rb @@ -0,0 +1,30 @@ +PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "../../..")).freeze +puts "Using project root: #{PROJECT_ROOT}" +TMP_GEM_ROOT = File.join(PROJECT_ROOT, "tmp", "bundler") +puts "Using tmp gem root: #{TMP_GEM_ROOT}" +TMP_GEM_BUILD = File.join(PROJECT_ROOT, "tmp", "build") +puts "Using tmp gem build: #{TMP_GEM_BUILD}" +ENV["APPRAISAL_UNDER_TEST"] = "1" + +RSpec.configure do |config| + config.raise_errors_for_deprecations! + + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + config.expect_with :rspec do |c| + c.syntax = :expect + end + + config.define_derived_metadata(:file_path => %r{spec/acceptance/}) do |metadata| + metadata[:type] = :acceptance + end + + config.before :suite do + FileUtils.rm_rf TMP_GEM_ROOT + FileUtils.rm_rf TMP_GEM_BUILD + end +end diff --git a/spec/fixtures/Gemfile-1.8 b/spec/fixtures/Gemfile-1.8 new file mode 100644 index 00000000..976c8496 --- /dev/null +++ b/spec/fixtures/Gemfile-1.8 @@ -0,0 +1,6 @@ +# These gems are locked for Ruby 1.8.7 compatibility +gem "i18n", "~> 0.6.0" +gem "activesupport", "~> 3.2.21" +gem "rake", "~> 10.5" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.3" # Removed from Std Lib in Ruby 3.5 diff --git a/spec/fixtures/Gemfile-2.0 b/spec/fixtures/Gemfile-2.0 new file mode 100644 index 00000000..75ff4f5d --- /dev/null +++ b/spec/fixtures/Gemfile-2.0 @@ -0,0 +1,4 @@ +# These gems are locked for Ruby 1.9 & 2.0 compatibility +gem "activesupport", "~> 4.2.7" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.3" # Removed from Std Lib in Ruby 3.5 diff --git a/spec/fixtures/Gemfile-2.1 b/spec/fixtures/Gemfile-2.1 new file mode 100644 index 00000000..71901a8d --- /dev/null +++ b/spec/fixtures/Gemfile-2.1 @@ -0,0 +1,4 @@ +# These gems are locked for Ruby 2.1 compatibility +gem "activesupport", "~> 4.2.7" +gem "rack", "~> 1.6.5" +gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1d9f7366..9edeea8c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,48 +1,27 @@ # frozen_string_literal: true -require "rubygems" - -if ENV["CI"].nil? && ENV["DEBUG"] == "true" - ENV["VERBOSE"] = "true" - ruby_version = Gem::Version.new(RUBY_VERSION) - if ruby_version < Gem::Version.new("2.7") - # Use byebug in code - require "byebug" - else - # Use binding.break, binding.b, or debugger in code - require "debug" - end -end - # External Libraries require "active_support/core_ext/string/strip" require "rspec/pending_for" -# This library +# RSpec Support require "support/dependency_helpers" -require "support/acceptance_test_helpers" require "support/stream_helpers" -PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..")).freeze -TMP_GEM_ROOT = File.join(PROJECT_ROOT, "tmp", "bundler") -TMP_GEM_BUILD = File.join(PROJECT_ROOT, "tmp", "build") -ENV["APPRAISAL_UNDER_TEST"] = "1" - -RSpec.configure do |config| - config.raise_errors_for_deprecations! +# RSpec Configs +require "config/byebug" +require "config/rspec/rspec_block_is_expected" +require "config/rspec/rspec_core" + +# # Last thing before loading this gem is to setup code coverage +# begin +# # This does not require "simplecov", but +# require "kettle-soup-cover" +# # this next line has a side-effect of running `.simplecov` +# require "simplecov" if defined?(Kettle::Soup::Cover) && Kettle::Soup::Cover::DO_COV +# rescue LoadError +# nil +# end - config.define_derived_metadata(:file_path => %r{spec/acceptance/}) do |metadata| - metadata[:type] = :acceptance - end - - config.include AcceptanceTestHelpers, :type => :acceptance - - # disable monkey patching - # see: https://relishapp.com/rspec/rspec-core/v/3-8/docs/configuration/zero-monkey-patching-mode - config.disable_monkey_patching! - - config.before :suite do - FileUtils.rm_rf TMP_GEM_ROOT - FileUtils.rm_rf TMP_GEM_BUILD - end -end +# This library +require "support/acceptance_test_helpers" diff --git a/spec/support/acceptance_test_helpers.rb b/spec/support/acceptance_test_helpers.rb index b721be90..60ecba5b 100644 --- a/spec/support/acceptance_test_helpers.rb +++ b/spec/support/acceptance_test_helpers.rb @@ -195,3 +195,7 @@ def run(command, raise_on_error = true) end end end + +RSpec.configure do |config| + config.include AcceptanceTestHelpers, :type => :acceptance +end From 81657fd34a7ace9dfbb554ab1d15da6ca3a4ab9b Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 13 Jul 2025 22:40:27 +0000 Subject: [PATCH 32/60] =?UTF-8?q?=F0=9F=91=B7=20set=20matrix.experimental?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/coverage.yml | 1 + .github/workflows/current-runtime-heads.yml | 3 +++ .github/workflows/current.yml | 3 +++ .github/workflows/jruby-9-4.yml | 1 + .github/workflows/ruby-2-3.yml | 1 + .github/workflows/ruby-2-4.yml | 1 + .github/workflows/ruby-2-5.yml | 1 + .github/workflows/ruby-2-6.yml | 1 + .github/workflows/ruby-2-7.yml | 1 + .github/workflows/ruby-3-0.yml | 1 + .github/workflows/ruby-3-1.yml | 1 + .github/workflows/ruby-3-2.yml | 1 + .github/workflows/ruby-3-3.yml | 2 ++ .github/workflows/style.yml | 1 + 14 files changed, 19 insertions(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f3aadc58..91f1a2be 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -55,6 +55,7 @@ jobs: exec_cmd: "rake test" rubygems: latest bundler: latest + experimental: false steps: - name: Checkout diff --git a/.github/workflows/current-runtime-heads.yml b/.github/workflows/current-runtime-heads.yml index df291ba7..4bdc0c37 100644 --- a/.github/workflows/current-runtime-heads.yml +++ b/.github/workflows/current-runtime-heads.yml @@ -47,6 +47,7 @@ jobs: exec_cmd: "rake test" rubygems: latest bundler: latest + experimental: true # truffleruby - ruby: "truffleruby" @@ -55,6 +56,7 @@ jobs: experimental: true rubygems: default bundler: default + experimental: true # jruby - ruby: "jruby" @@ -63,6 +65,7 @@ jobs: experimental: true rubygems: default bundler: default + experimental: true steps: - name: Checkout diff --git a/.github/workflows/current.yml b/.github/workflows/current.yml index 338fcb59..2942eb25 100644 --- a/.github/workflows/current.yml +++ b/.github/workflows/current.yml @@ -46,6 +46,7 @@ jobs: exec_cmd: "rake test" rubygems: latest bundler: latest + experimental: false # truffleruby - ruby: "truffleruby" @@ -53,6 +54,7 @@ jobs: exec_cmd: "rake test" rubygems: default bundler: default + experimental: false # jruby - ruby: "jruby" @@ -60,6 +62,7 @@ jobs: exec_cmd: "rake test" rubygems: default bundler: default + experimental: false steps: - name: Checkout diff --git a/.github/workflows/jruby-9-4.yml b/.github/workflows/jruby-9-4.yml index c2eb0c9e..784bbadc 100644 --- a/.github/workflows/jruby-9-4.yml +++ b/.github/workflows/jruby-9-4.yml @@ -45,6 +45,7 @@ jobs: exec_cmd: "rake test" rubygems: default bundler: default + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-2-3.yml b/.github/workflows/ruby-2-3.yml index a3d69609..9d0e087c 100755 --- a/.github/workflows/ruby-2-3.yml +++ b/.github/workflows/ruby-2-3.yml @@ -45,6 +45,7 @@ jobs: exec_cmd: "rake test" rubygems: "3.3.27" bundler: "2.3.27" + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-2-4.yml b/.github/workflows/ruby-2-4.yml index 96d45803..41bac60f 100755 --- a/.github/workflows/ruby-2-4.yml +++ b/.github/workflows/ruby-2-4.yml @@ -45,6 +45,7 @@ jobs: exec_cmd: "rake test" rubygems: "3.3.27" bundler: "2.3.27" + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-2-5.yml b/.github/workflows/ruby-2-5.yml index 02e13d90..f533980d 100755 --- a/.github/workflows/ruby-2-5.yml +++ b/.github/workflows/ruby-2-5.yml @@ -45,6 +45,7 @@ jobs: exec_cmd: "rake test" rubygems: "3.3.27" bundler: "2.3.27" + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-2-6.yml b/.github/workflows/ruby-2-6.yml index 312c5aed..272f60c1 100644 --- a/.github/workflows/ruby-2-6.yml +++ b/.github/workflows/ruby-2-6.yml @@ -45,6 +45,7 @@ jobs: exec_cmd: "rake test" rubygems: '3.4.22' bundler: '2.4.22' + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-2-7.yml b/.github/workflows/ruby-2-7.yml index 95512153..40bdd6ce 100644 --- a/.github/workflows/ruby-2-7.yml +++ b/.github/workflows/ruby-2-7.yml @@ -45,6 +45,7 @@ jobs: exec_cmd: "rake test" rubygems: '3.4.22' bundler: '2.4.22' + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-3-0.yml b/.github/workflows/ruby-3-0.yml index 36ab412a..4e9181d5 100644 --- a/.github/workflows/ruby-3-0.yml +++ b/.github/workflows/ruby-3-0.yml @@ -45,6 +45,7 @@ jobs: exec_cmd: "rake test" rubygems: '3.5.23' bundler: '2.5.23' + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-3-1.yml b/.github/workflows/ruby-3-1.yml index f3e7c77e..1010a3a6 100644 --- a/.github/workflows/ruby-3-1.yml +++ b/.github/workflows/ruby-3-1.yml @@ -45,6 +45,7 @@ jobs: exec_cmd: "rake test" rubygems: latest bundler: latest + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-3-2.yml b/.github/workflows/ruby-3-2.yml index 73619238..439a10ec 100644 --- a/.github/workflows/ruby-3-2.yml +++ b/.github/workflows/ruby-3-2.yml @@ -43,6 +43,7 @@ jobs: exec_cmd: "rake test" rubygems: latest bundler: latest + experimental: false steps: - name: Checkout diff --git a/.github/workflows/ruby-3-3.yml b/.github/workflows/ruby-3-3.yml index df803876..45a6e681 100644 --- a/.github/workflows/ruby-3-3.yml +++ b/.github/workflows/ruby-3-3.yml @@ -45,6 +45,8 @@ jobs: exec_cmd: "rake test" rubygems: latest bundler: latest + experimental: false + steps: - name: Checkout diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index b154d9f3..2e883819 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -43,6 +43,7 @@ jobs: exec_cmd: "rake rubocop_gradual:check" rubygems: latest bundler: latest + experimental: false steps: - name: Checkout From 994161b1f7c69b07074cfb2c8ba40f52cf02f29d Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 13 Jul 2025 22:43:59 +0000 Subject: [PATCH 33/60] =?UTF-8?q?=F0=9F=9A=A8=20Linting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .rubocop_gradual.lock | 113 +++++++++++------------- gemfiles/modular/thor/r2.6/v1.3.gemfile | 2 +- gemfiles/modular/thor/r3/v1.3.gemfile | 2 +- 3 files changed, 56 insertions(+), 61 deletions(-) diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 3367ae73..20625b7a 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -1,16 +1,11 @@ { - "Gemfile:2056742212": [ - [41, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [43, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787], - [45, 3, 4, "Security/Eval: The use of `eval` is a serious security risk.", 2087429787] - ], "bin/bundle:41466308": [ [66, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] ], "lib/appraisal/appraisal_file.rb:3950440874": [ [13, 5, 52, "Style/ClassMethodsDefinitions: Use `class << self` to define a class method.", 946226050] ], - "lib/appraisal/cli.rb:435288507": [ + "lib/appraisal/cli.rb:2498658185": [ [116, 5, 410, "Style/MissingRespondToMissing: When using `method_missing`, define `respond_to_missing?`.", 1969529734] ], "lib/appraisal/customize.rb:473220891": [ @@ -46,62 +41,62 @@ "spec/acceptance/cli/update_spec.rb:3754424074": [ [3, 23, 18, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 3752509585] ], - "spec/acceptance/cli/version_spec.rb:2850459497": [ + "spec/acceptance/cli/version_spec.rb:3359607259": [ [3, 23, 19, "RSpec/DescribeMethod: The second argument to describe should be the method being tested. '#instance' or '.class'.", 316256858] ], - "spec/appraisal/appraisal_file_spec.rb:1896479557": [ - [28, 18, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], - [33, 7, 57, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 511689843], - [41, 20, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], - [41, 33, 39, "RSpec/ExpectChange: Prefer `change(Appraisal::Customize, :heading)`.", 513325635], - [45, 7, 63, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1527582647], - [53, 20, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], - [53, 33, 45, "RSpec/ExpectChange: Prefer `change(Appraisal::Customize, :single_quotes)`.", 627072007], - [57, 7, 77, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1960750461], - [65, 11, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] - ], - "spec/appraisal/appraisal_spec.rb:3939376245": [ - [33, 11, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2511581329], - [90, 11, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1120511218], - [95, 7, 83, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [96].", 1453890366], + "spec/appraisal/appraisal_file_spec.rb:3560841911": [ + [27, 18, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [32, 7, 57, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 511689843], + [40, 20, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [40, 33, 39, "RSpec/ExpectChange: Prefer `change(Appraisal::Customize, :heading)`.", 513325635], + [44, 7, 63, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1527582647], + [52, 20, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [52, 33, 45, "RSpec/ExpectChange: Prefer `change(Appraisal::Customize, :single_quotes)`.", 627072007], + [56, 7, 77, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 1960750461], + [64, 11, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] + ], + "spec/appraisal/appraisal_spec.rb:3208649742": [ + [32, 11, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2511581329], + [89, 11, 23, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1120511218], + [94, 7, 83, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [95].", 1453890366], + [94, 13, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [95, 7, 82, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [94].", 1614459968], [95, 13, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], - [96, 7, 82, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [95].", 1614459968], - [96, 13, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], - [97, 61, 20, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 2281802167], - [104, 9, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], - [114, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], - [120, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], - [126, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192] - ], - "spec/appraisal/customize_spec.rb:3636242792": [ - [7, 1, 4472, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 194570577], - [17, 3, 13, "RSpec/SubjectDeclaration: Use subject explicitly rather than using let", 3282510975], - [25, 3, 564, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 3336288078], - [27, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], - [43, 3, 286, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 4222920637], - [45, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], - [55, 3, 2985, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [13/5]", 1576524985], - [65, 7, 62, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [66, 67, 68].", 123979604], - [66, 7, 72, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 67, 68].", 3240119264], - [67, 7, 74, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 66, 68].", 3701550880], - [68, 7, 85, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 66, 67].", 3874694796], - [72, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] - ], - "spec/appraisal/gemfile_spec.rb:3969538335": [ - [228, 11, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3608128140], - [229, 13, 13, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 420381022], - [236, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3511037132], - [246, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3100155342], - [256, 11, 24, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3242693747], - [259, 13, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 105800534], - [282, 13, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 179066369], - [313, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3912615366], - [357, 13, 14, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2832187185], - [415, 13, 22, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 772581599], - [425, 11, 20, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1076107314] - ], - "spec/appraisal/utils_spec.rb:2286225770": [ - [62, 17, 58, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 1573223692] + [96, 61, 20, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 2281802167], + [103, 9, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [113, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [119, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192], + [125, 7, 10, "RSpec/InstanceVariable: Avoid instance variables - use let, a method call, or a local variable (if possible).", 4097172192] + ], + "spec/appraisal/customize_spec.rb:2426121299": [ + [6, 1, 4472, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 194570577], + [16, 3, 13, "RSpec/SubjectDeclaration: Use subject explicitly rather than using let", 3282510975], + [24, 3, 564, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 3336288078], + [26, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [42, 3, 286, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5]", 4222920637], + [44, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441], + [54, 3, 2985, "RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [13/5]", 1576524985], + [64, 7, 62, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [65, 66, 67].", 123979604], + [65, 7, 72, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [64, 66, 67].", 3240119264], + [66, 7, 74, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [64, 65, 67].", 3701550880], + [67, 7, 85, "RSpec/ReceiveMessages: Use `receive_messages` instead of multiple stubs on lines [64, 65, 66].", 3874694796], + [71, 7, 7, "RSpec/NamedSubject: Name your test subject if you need to reference it explicitly.", 1892732441] + ], + "spec/appraisal/gemfile_spec.rb:2966428452": [ + [227, 11, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3608128140], + [228, 13, 13, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 420381022], + [235, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3511037132], + [245, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3100155342], + [255, 11, 24, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3242693747], + [258, 13, 17, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 105800534], + [281, 13, 16, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 179066369], + [312, 13, 15, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 3912615366], + [356, 13, 14, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 2832187185], + [414, 13, 22, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 772581599], + [424, 11, 20, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1076107314] + ], + "spec/appraisal/utils_spec.rb:213138161": [ + [61, 17, 58, "RSpec/VerifiedDoubles: Prefer using verifying doubles over normal doubles.", 1573223692] ], "spec/support/acceptance_test_helpers.rb:3908433317": [ [149, 5, 32, "Style/InvertibleUnlessCondition: Prefer `if $?.exitstatus == 0` over `unless $?.exitstatus != 0`.", 4187517264] diff --git a/gemfiles/modular/thor/r2.6/v1.3.gemfile b/gemfiles/modular/thor/r2.6/v1.3.gemfile index 4ef8127f..3df6c0df 100644 --- a/gemfiles/modular/thor/r2.6/v1.3.gemfile +++ b/gemfiles/modular/thor/r2.6/v1.3.gemfile @@ -1,2 +1,2 @@ # Ruby >= 2.6 (dependency of rails) -gem "thor", "~> 1.3.2" \ No newline at end of file +gem "thor", "~> 1.3.2" diff --git a/gemfiles/modular/thor/r3/v1.3.gemfile b/gemfiles/modular/thor/r3/v1.3.gemfile index 4ef8127f..3df6c0df 100644 --- a/gemfiles/modular/thor/r3/v1.3.gemfile +++ b/gemfiles/modular/thor/r3/v1.3.gemfile @@ -1,2 +1,2 @@ # Ruby >= 2.6 (dependency of rails) -gem "thor", "~> 1.3.2" \ No newline at end of file +gem "thor", "~> 1.3.2" From 5986c145893c44adc02e09c22d1916a4b4e7476c Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 14 Jul 2025 12:04:15 +0000 Subject: [PATCH 34/60] =?UTF-8?q?=F0=9F=93=8C=20Pin=20to=20bundled=20gems?= =?UTF-8?q?=20for=20older=20rubies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/dbnavigator.xml | 3 +++ gemfiles/modular/logger/r1/default.gemfile | 1 + gemfiles/modular/logger/{r2 => r2.3}/v1.5.gemfile | 0 gemfiles/modular/logger/r2/default.gemfile | 1 + gemfiles/modular/ruby_2_3.gemfile | 2 +- gemfiles/modular/ruby_2_4.gemfile | 2 +- gemfiles/modular/ruby_2_5.gemfile | 2 +- gemfiles/modular/ruby_2_6.gemfile | 2 +- gemfiles/modular/ruby_2_7.gemfile | 2 +- gemfiles/modular/uri/r1/default.gemfile | 1 + gemfiles/modular/uri/{r2 => r2.5}/v0.gemfile | 0 gemfiles/modular/uri/r2/default.gemfile | 1 + gemfiles/modular/x_std_libs/r1/libs.gemfile | 4 ++-- gemfiles/modular/x_std_libs/r2.3/libs.gemfile | 2 ++ gemfiles/modular/x_std_libs/r2.5/libs.gemfile | 2 ++ gemfiles/modular/x_std_libs/r2/libs.gemfile | 4 ++-- spec/acceptance/bundle_without_spec.rb | 7 ++++++- 17 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 gemfiles/modular/logger/r1/default.gemfile rename gemfiles/modular/logger/{r2 => r2.3}/v1.5.gemfile (100%) create mode 100644 gemfiles/modular/logger/r2/default.gemfile create mode 100644 gemfiles/modular/uri/r1/default.gemfile rename gemfiles/modular/uri/{r2 => r2.5}/v0.gemfile (100%) create mode 100644 gemfiles/modular/uri/r2/default.gemfile create mode 100644 gemfiles/modular/x_std_libs/r2.3/libs.gemfile create mode 100644 gemfiles/modular/x_std_libs/r2.5/libs.gemfile diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml index 8f9a1232..c74ee11f 100644 --- a/.idea/dbnavigator.xml +++ b/.idea/dbnavigator.xml @@ -10,6 +10,9 @@ + + + diff --git a/gemfiles/modular/logger/r1/default.gemfile b/gemfiles/modular/logger/r1/default.gemfile new file mode 100644 index 00000000..ba1f2c97 --- /dev/null +++ b/gemfiles/modular/logger/r1/default.gemfile @@ -0,0 +1 @@ +# Use the default logger library that ships with Ruby \ No newline at end of file diff --git a/gemfiles/modular/logger/r2/v1.5.gemfile b/gemfiles/modular/logger/r2.3/v1.5.gemfile similarity index 100% rename from gemfiles/modular/logger/r2/v1.5.gemfile rename to gemfiles/modular/logger/r2.3/v1.5.gemfile diff --git a/gemfiles/modular/logger/r2/default.gemfile b/gemfiles/modular/logger/r2/default.gemfile new file mode 100644 index 00000000..ba1f2c97 --- /dev/null +++ b/gemfiles/modular/logger/r2/default.gemfile @@ -0,0 +1 @@ +# Use the default logger library that ships with Ruby \ No newline at end of file diff --git a/gemfiles/modular/ruby_2_3.gemfile b/gemfiles/modular/ruby_2_3.gemfile index d2623b52..4bc82e25 100644 --- a/gemfiles/modular/ruby_2_3.gemfile +++ b/gemfiles/modular/ruby_2_3.gemfile @@ -2,4 +2,4 @@ eval_gemfile("thor/r2/v1.2.gemfile") -eval_gemfile("x_std_libs/r2/libs.gemfile") +eval_gemfile("x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_4.gemfile b/gemfiles/modular/ruby_2_4.gemfile index d2623b52..4bc82e25 100644 --- a/gemfiles/modular/ruby_2_4.gemfile +++ b/gemfiles/modular/ruby_2_4.gemfile @@ -2,4 +2,4 @@ eval_gemfile("thor/r2/v1.2.gemfile") -eval_gemfile("x_std_libs/r2/libs.gemfile") +eval_gemfile("x_std_libs/r2.3/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_5.gemfile b/gemfiles/modular/ruby_2_5.gemfile index d2623b52..ddd40150 100644 --- a/gemfiles/modular/ruby_2_5.gemfile +++ b/gemfiles/modular/ruby_2_5.gemfile @@ -2,4 +2,4 @@ eval_gemfile("thor/r2/v1.2.gemfile") -eval_gemfile("x_std_libs/r2/libs.gemfile") +eval_gemfile("x_std_libs/r2.5/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_6.gemfile b/gemfiles/modular/ruby_2_6.gemfile index 1dc52778..b2d43e41 100644 --- a/gemfiles/modular/ruby_2_6.gemfile +++ b/gemfiles/modular/ruby_2_6.gemfile @@ -2,4 +2,4 @@ eval_gemfile("thor/r2.6/v1.3.gemfile") -eval_gemfile("x_std_libs/r2/libs.gemfile") +eval_gemfile("x_std_libs/r2.5/libs.gemfile") diff --git a/gemfiles/modular/ruby_2_7.gemfile b/gemfiles/modular/ruby_2_7.gemfile index 1dc52778..b2d43e41 100644 --- a/gemfiles/modular/ruby_2_7.gemfile +++ b/gemfiles/modular/ruby_2_7.gemfile @@ -2,4 +2,4 @@ eval_gemfile("thor/r2.6/v1.3.gemfile") -eval_gemfile("x_std_libs/r2/libs.gemfile") +eval_gemfile("x_std_libs/r2.5/libs.gemfile") diff --git a/gemfiles/modular/uri/r1/default.gemfile b/gemfiles/modular/uri/r1/default.gemfile new file mode 100644 index 00000000..ec933a75 --- /dev/null +++ b/gemfiles/modular/uri/r1/default.gemfile @@ -0,0 +1 @@ +# Use the default uri library that ships with Ruby \ No newline at end of file diff --git a/gemfiles/modular/uri/r2/v0.gemfile b/gemfiles/modular/uri/r2.5/v0.gemfile similarity index 100% rename from gemfiles/modular/uri/r2/v0.gemfile rename to gemfiles/modular/uri/r2.5/v0.gemfile diff --git a/gemfiles/modular/uri/r2/default.gemfile b/gemfiles/modular/uri/r2/default.gemfile new file mode 100644 index 00000000..ec933a75 --- /dev/null +++ b/gemfiles/modular/uri/r2/default.gemfile @@ -0,0 +1 @@ +# Use the default uri library that ships with Ruby \ No newline at end of file diff --git a/gemfiles/modular/x_std_libs/r1/libs.gemfile b/gemfiles/modular/x_std_libs/r1/libs.gemfile index 4313604c..8f37cde2 100644 --- a/gemfiles/modular/x_std_libs/r1/libs.gemfile +++ b/gemfiles/modular/x_std_libs/r1/libs.gemfile @@ -1,2 +1,2 @@ -eval_gemfile "../../logger/r2/v1.5.gemfile" -eval_gemfile "../../uri/r2/v0.gemfile" +eval_gemfile "../../logger/r1/default.gemfile" +eval_gemfile "../../uri/r1/default.gemfile" diff --git a/gemfiles/modular/x_std_libs/r2.3/libs.gemfile b/gemfiles/modular/x_std_libs/r2.3/libs.gemfile new file mode 100644 index 00000000..22721961 --- /dev/null +++ b/gemfiles/modular/x_std_libs/r2.3/libs.gemfile @@ -0,0 +1,2 @@ +eval_gemfile "../../logger/r2.3/v1.5.gemfile" +eval_gemfile "../../uri/r2/default.gemfile" diff --git a/gemfiles/modular/x_std_libs/r2.5/libs.gemfile b/gemfiles/modular/x_std_libs/r2.5/libs.gemfile new file mode 100644 index 00000000..947d54e1 --- /dev/null +++ b/gemfiles/modular/x_std_libs/r2.5/libs.gemfile @@ -0,0 +1,2 @@ +eval_gemfile "../../logger/r2.3/v1.5.gemfile" +eval_gemfile "../../uri/r2.5/v0.gemfile" diff --git a/gemfiles/modular/x_std_libs/r2/libs.gemfile b/gemfiles/modular/x_std_libs/r2/libs.gemfile index 4313604c..21a58257 100644 --- a/gemfiles/modular/x_std_libs/r2/libs.gemfile +++ b/gemfiles/modular/x_std_libs/r2/libs.gemfile @@ -1,2 +1,2 @@ -eval_gemfile "../../logger/r2/v1.5.gemfile" -eval_gemfile "../../uri/r2/v0.gemfile" +eval_gemfile "../../logger/r2/default.gemfile" +eval_gemfile "../../uri/r2/default.gemfile" diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index 9d9fdd8b..02d83350 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -3,8 +3,13 @@ RSpec.describe "Bundle without group" do it "config set --local without group is honored by Bundler" do reason = "config set --local without group support seems broken, see: https://github.com/rubygems/rubygems/issues/8518" + # The seeming randomness of the below behavior may be due to the many layers of bundler here. + # The spec suite itself runs in bundler, and then we further execute bundler within tests. # Somehow this spec passes on truffleruby *only*!! - pending_for(:engine => "ruby", :reason => reason) + # For some reason it is not working on Ruby v3 + pending_for(:engine => "ruby", :versions => %w(3.0.7 3.1.6 3.2.7 3.3.7 3.4.4), :reason => reason) + # And only some versions of Ruby v2 + pending_for(:engine => "ruby", :versions => %w(2.3.8 2.4.10 2.5.9), :reason => reason) pending_for(:engine => "jruby", :reason => reason) build_gems %w[pancake orange_juice waffle coffee sausage soda] From 16e5421c8f3233d418acd2148becd836131d513b Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 14 Jul 2025 12:06:02 +0000 Subject: [PATCH 35/60] =?UTF-8?q?=F0=9F=9A=A8=20Linting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gemfiles/modular/logger/r1/default.gemfile | 2 +- gemfiles/modular/logger/r2/default.gemfile | 2 +- gemfiles/modular/uri/r1/default.gemfile | 2 +- gemfiles/modular/uri/r2/default.gemfile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gemfiles/modular/logger/r1/default.gemfile b/gemfiles/modular/logger/r1/default.gemfile index ba1f2c97..b9b0ede6 100644 --- a/gemfiles/modular/logger/r1/default.gemfile +++ b/gemfiles/modular/logger/r1/default.gemfile @@ -1 +1 @@ -# Use the default logger library that ships with Ruby \ No newline at end of file +# Use the default logger library that ships with Ruby diff --git a/gemfiles/modular/logger/r2/default.gemfile b/gemfiles/modular/logger/r2/default.gemfile index ba1f2c97..b9b0ede6 100644 --- a/gemfiles/modular/logger/r2/default.gemfile +++ b/gemfiles/modular/logger/r2/default.gemfile @@ -1 +1 @@ -# Use the default logger library that ships with Ruby \ No newline at end of file +# Use the default logger library that ships with Ruby diff --git a/gemfiles/modular/uri/r1/default.gemfile b/gemfiles/modular/uri/r1/default.gemfile index ec933a75..cb13f736 100644 --- a/gemfiles/modular/uri/r1/default.gemfile +++ b/gemfiles/modular/uri/r1/default.gemfile @@ -1 +1 @@ -# Use the default uri library that ships with Ruby \ No newline at end of file +# Use the default uri library that ships with Ruby diff --git a/gemfiles/modular/uri/r2/default.gemfile b/gemfiles/modular/uri/r2/default.gemfile index ec933a75..cb13f736 100644 --- a/gemfiles/modular/uri/r2/default.gemfile +++ b/gemfiles/modular/uri/r2/default.gemfile @@ -1 +1 @@ -# Use the default uri library that ships with Ruby \ No newline at end of file +# Use the default uri library that ships with Ruby From fe149761e5dcb2c8e09d19f57d4e91d3d520fbab Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 14 Jul 2025 12:08:13 +0000 Subject: [PATCH 36/60] =?UTF-8?q?=F0=9F=94=A7=20Fix=20workflow=20syntax?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/current-runtime-heads.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/current-runtime-heads.yml b/.github/workflows/current-runtime-heads.yml index 4bdc0c37..5fc806e6 100644 --- a/.github/workflows/current-runtime-heads.yml +++ b/.github/workflows/current-runtime-heads.yml @@ -53,7 +53,6 @@ jobs: - ruby: "truffleruby" gemfile: "dep-heads" exec_cmd: "rake test" - experimental: true rubygems: default bundler: default experimental: true @@ -62,7 +61,6 @@ jobs: - ruby: "jruby" gemfile: "dep-heads" exec_cmd: "rake test" - experimental: true rubygems: default bundler: default experimental: true From 5b7de80890b23d97225717dd9081ba42d18d6d21 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 14 Jul 2025 12:15:17 +0000 Subject: [PATCH 37/60] =?UTF-8?q?=F0=9F=92=9A=20pending=20for=20certain=20?= =?UTF-8?q?Rubies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/acceptance/bundle_without_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index 02d83350..77c6989f 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -7,7 +7,7 @@ # The spec suite itself runs in bundler, and then we further execute bundler within tests. # Somehow this spec passes on truffleruby *only*!! # For some reason it is not working on Ruby v3 - pending_for(:engine => "ruby", :versions => %w(3.0.7 3.1.6 3.2.7 3.3.7 3.4.4), :reason => reason) + pending_for(:engine => "ruby", :versions => %w(3.0.7 3.1.7 3.2.8 3.3.8 3.4.4), :reason => reason) # And only some versions of Ruby v2 pending_for(:engine => "ruby", :versions => %w(2.3.8 2.4.10 2.5.9), :reason => reason) pending_for(:engine => "jruby", :reason => reason) From 114916af61d4535907499e579839f3369b106445 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 14 Jul 2025 12:34:45 +0000 Subject: [PATCH 38/60] =?UTF-8?q?=F0=9F=91=B7=20Turn=20code=20coverage=20b?= =?UTF-8?q?ack=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/spec_helper.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9edeea8c..13fce886 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -13,15 +13,15 @@ require "config/rspec/rspec_block_is_expected" require "config/rspec/rspec_core" -# # Last thing before loading this gem is to setup code coverage -# begin -# # This does not require "simplecov", but -# require "kettle-soup-cover" -# # this next line has a side-effect of running `.simplecov` -# require "simplecov" if defined?(Kettle::Soup::Cover) && Kettle::Soup::Cover::DO_COV -# rescue LoadError -# nil -# end +# Last thing before loading this gem is to setup code coverage +begin + # This does not require "simplecov", but + require "kettle-soup-cover" + # this next line has a side-effect of running `.simplecov` + require "simplecov" if defined?(Kettle::Soup::Cover) && Kettle::Soup::Cover::DO_COV +rescue LoadError + nil +end # This library require "support/acceptance_test_helpers" From f7b777b32092beb66b5924c50dbbe959ccc2aeba Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 15 Jul 2025 23:52:39 +0000 Subject: [PATCH 39/60] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20kettle-soup-cover=20?= =?UTF-8?q?v1.0.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/appraisal2.iml | 290 ++++++++++++++++++++++++++---- .idea/vcs.xml | 4 + Gemfile.lock | 36 ++-- gemfiles/modular/coverage.gemfile | 7 +- 4 files changed, 283 insertions(+), 54 deletions(-) diff --git a/.idea/appraisal2.iml b/.idea/appraisal2.iml index 327172e3..cff17612 100644 --- a/.idea/appraisal2.iml +++ b/.idea/appraisal2.iml @@ -43,6 +43,44 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -706,7 +744,7 @@ - + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + @@ -817,6 +855,38 @@ + + + + + + + + + + + + + + + + + @@ -2321,7 +2391,7 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - + + - - - + @@ -2401,6 +2501,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2618,6 +2797,44 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -2974,5 +3191,6 @@ + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 83067447..1749f799 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -3,5 +3,9 @@ + + + + \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index aedd265b..b1a5d2e2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,12 +1,3 @@ -GIT - remote: https://github.com/dashingrocket/simplecov-cobertura - revision: b72eacdeab8b055533debc6fd150cb977db0ca3e - branch: main - specs: - simplecov-cobertura (2.1.1.pre.dev) - rexml - simplecov (~> 0.19) - GIT remote: https://github.com/pboling/yard-junk revision: 54ccebabbfa9a9cd44d0b991687ebbfd22c32b55 @@ -43,6 +34,7 @@ GEM securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) + ansi (1.5.0) ast (2.4.3) backports (3.25.1) base64 (0.3.0) @@ -87,10 +79,19 @@ GEM dry-inflector (~> 1.0) dry-logic (~> 1.4) zeitwerk (~> 2.6) - erb (5.0.1) + erb (5.0.2) i18n (1.14.7) concurrent-ruby (~> 1.0) json (2.12.2) + kettle-soup-cover (1.0.10) + simplecov (~> 0.22) + simplecov-cobertura (~> 3.0) + simplecov-console (~> 0.9, >= 0.9.3) + simplecov-html (~> 0.13, >= 0.13.1) + simplecov-lcov (~> 0.8) + simplecov-rcov (~> 0.3, >= 0.3.7) + simplecov_json_formatter (~> 0.1, >= 0.1.4) + version_gem (~> 1.1, >= 1.1.8) kramdown (2.5.1) rexml (>= 3.3.9) kramdown-parser-gfm (1.1.0) @@ -222,7 +223,17 @@ GEM docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) + simplecov-cobertura (3.0.0) + rexml + simplecov (~> 0.19) + simplecov-console (0.9.3) + ansi + simplecov + terminal-table simplecov-html (0.13.1) + simplecov-lcov (0.8.0) + simplecov-rcov (0.3.7) + simplecov (>= 0.4.1) simplecov_json_formatter (0.1.4) standard (1.50.0) language_server-protocol (~> 3.17.0.2) @@ -243,6 +254,8 @@ GEM standard-performance (>= 1.3.1, < 2) version_gem (>= 1.1.4, < 3) stringio (3.1.7) + terminal-table (4.0.0) + unicode-display_width (>= 1.1.1, < 4) thor (1.3.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) @@ -271,10 +284,10 @@ DEPENDENCIES appraisal2! benchmark (~> 0.4) bundler-audit (~> 0.9.2) + kettle-soup-cover (~> 1.0, >= 1.0.10) kramdown (~> 2.5, >= 2.5.1) kramdown-parser-gfm (~> 1.1) logger (~> 1.7) - ostruct (~> 0.6, >= 0.6.1) rdoc (~> 6.11) reek (~> 6.4) rspec (~> 3.13) @@ -285,7 +298,6 @@ DEPENDENCIES rubocop-minitest (~> 0.36) rubocop-packaging (~> 0.6, >= 0.6.0) rubocop-rspec (~> 3.2) - simplecov-cobertura! standard (~> 1.47) thor (~> 1.3.2) uri (~> 1.0, >= 1.0.3) diff --git a/gemfiles/modular/coverage.gemfile b/gemfiles/modular/coverage.gemfile index 6a20ab1a..5dc932ce 100644 --- a/gemfiles/modular/coverage.gemfile +++ b/gemfiles/modular/coverage.gemfile @@ -3,9 +3,4 @@ # We run code coverage on the latest version of Ruby only. # Coverage -# All coverage gems are listed in gemspec dependencies. -# But fix in the main branch (https://github.com/dashingrocket/simplecov-cobertura/pull/32) -# needed to prevent the circular require warning and stacktrace. -gem "simplecov-cobertura", :github => "dashingrocket/simplecov-cobertura", :branch => "main" - -gem "ostruct", "~> 0.6", ">= 0.6.1" # Ruby >= 2.5 +gem "kettle-soup-cover", "~> 1.0", ">= 1.0.10"# Ruby >= 2.7 From ccda36bb67f3b087e21d6d35b8244e2e0634705b Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 19:52:38 +0000 Subject: [PATCH 40/60] =?UTF-8?q?=F0=9F=93=9D=20Update=20gemspec=20email?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appraisal2.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appraisal2.gemspec b/appraisal2.gemspec index 854a33a1..3e7e9561 100644 --- a/appraisal2.gemspec +++ b/appraisal2.gemspec @@ -11,8 +11,8 @@ Gem::Specification.new do |spec| spec.name = "appraisal2" spec.version = Appraisal::VERSION.dup spec.platform = Gem::Platform::RUBY - spec.authors = ["Joe Ferris", "Prem Sichanugrist"] - spec.email = ["jferris@thoughtbot.com", "prem@thoughtbot.com"] + spec.authors = ["Peter Boling", "Joe Ferris", "Prem Sichanugrist"] + spec.email = ["galtzo@floss.com"] spec.homepage = "http://github.com/appraisal-rb/appraisal2" spec.summary = "Find out what your Ruby gems are worth" spec.description = 'Appraisal integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."' From f03546275ca927c3177323f383de095e3c79bb81 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 19:52:52 +0000 Subject: [PATCH 41/60] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Develop=20on=20Ruby?= =?UTF-8?q?=203.4.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tool-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tool-versions b/.tool-versions index ca745c6d..27a8619d 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 3.4.4 +ruby 3.4.5 From 17501457813009b696f576c8d2b0cb351f7d2337 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 19:53:03 +0000 Subject: [PATCH 42/60] =?UTF-8?q?=F0=9F=91=B7=20Add=20QLTY.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .qlty/qlty.toml | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 .qlty/qlty.toml diff --git a/.qlty/qlty.toml b/.qlty/qlty.toml new file mode 100644 index 00000000..9ae9cae8 --- /dev/null +++ b/.qlty/qlty.toml @@ -0,0 +1,79 @@ +# For a guide to configuration, visit https://qlty.sh/d/config +# Or for a full reference, visit https://qlty.sh/d/qlty-toml +config_version = "0" + +exclude_patterns = [ + "*_min.*", + "*-min.*", + "*.min.*", + "**/.yarn/**", + "**/*.d.ts", + "**/assets/**", + "**/bin/**", + "**/bower_components/**", + "**/build/**", + "**/cache/**", + "**/config/**", + "**/.devcontainer", + "**/db/**", + "**/deps/**", + "**/dist/**", + "**/doc/**", + "**/docs/**", + "**/extern/**", + "**/external/**", + "**/generated/**", + "**/Godeps/**", + "**/gradlew/**", + "**/mvnw/**", + "**/node_modules/**", + "**/protos/**", + "**/seed/**", + "**/target/**", + "**/templates/**", + "**/testdata/**", + "**/vendor/**", + ".github/workflows/codeql-analysis.yml" +] + +test_patterns = [ + "**/test/**", + "**/spec/**", + "**/*.test.*", + "**/*.spec.*", + "**/*_test.*", + "**/*_spec.*", + "**/test_*.*", + "**/spec_*.*", +] + +[smells] +mode = "comment" + +[smells.boolean_logic] +threshold = 4 +enabled = true + +[smells.file_complexity] +threshold = 55 +enabled = false + +[smells.return_statements] +threshold = 4 +enabled = true + +[smells.nested_control_flow] +threshold = 4 +enabled = true + +[smells.function_parameters] +threshold = 4 +enabled = true + +[smells.function_complexity] +threshold = 5 +enabled = true + +[smells.duplication] +enabled = true +threshold = 20 \ No newline at end of file From 9a3eaa972dcddc5b3b7417226dddc015f0c5ff12 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 19:54:10 +0000 Subject: [PATCH 43/60] =?UTF-8?q?=F0=9F=93=9D=20Update=20SECURITY.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SECURITY.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index af661807..f60f9b34 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,20 +1,21 @@ - # Security Policy ## Supported Versions -Only the the latest version of this project is supported at a given time. If -you find a security issue with an older version, please try updating to the -latest version first. +| Version | Supported | +|----------|-----------| +| 1.latest | ✅ | -If for some reason you can't update to the latest version, please let us know -your reasons so that we can have a better understanding of your situation. +## Security contact information -## Reporting a Vulnerability +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. -For security inquiries or vulnerability reports, visit -. +## Additional Support -If you have any suggestions to improve this policy, visit . +If you are interested in support for versions older than the latest release, +please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate, +or find other sponsorship links in the [README]. - +[README]: README.md \ No newline at end of file From c03ebff4ae91b76516052a73e7733b761d331bfa Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 19:59:29 +0000 Subject: [PATCH 44/60] =?UTF-8?q?=F0=9F=93=9D=20Update=20gemspec=20metadat?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appraisal2.gemspec | 58 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/appraisal2.gemspec b/appraisal2.gemspec index 3e7e9561..a229249f 100644 --- a/appraisal2.gemspec +++ b/appraisal2.gemspec @@ -1,22 +1,60 @@ # frozen_string_literal: true -# TODO: Switch to require_relative once support for Ruby < 2 is dropped. -# require_relative "lib/appraisal/version" - -lib = File.expand_path("../lib", __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require "appraisal/version" +gem_version = + if RUBY_VERSION >= "3.1" + # Loading version into an anonymous module allows version.rb to get code coverage from SimpleCov! + # See: https://github.com/simplecov-ruby/simplecov/issues/557#issuecomment-2630782358 + Module.new.tap { |mod| Kernel.load("lib/appraisal/version.rb", mod) }::Appraisal::VERSION + else + # TODO: Remove this hack once support for Ruby 3.0 and below is removed + Kernel.load("lib/appraisal/version.rb") + g_ver = Appraisal::VERSION + Appraisal.send(:remove_const, :VERSION) + g_ver + end Gem::Specification.new do |spec| spec.name = "appraisal2" - spec.version = Appraisal::VERSION.dup - spec.platform = Gem::Platform::RUBY + spec.version = gem_version spec.authors = ["Peter Boling", "Joe Ferris", "Prem Sichanugrist"] spec.email = ["galtzo@floss.com"] - spec.homepage = "http://github.com/appraisal-rb/appraisal2" + + # Linux distros often package gems and securely certify them independent + # of the official RubyGem certification process. Allowed via ENV["SKIP_GEM_SIGNING"] + # Ref: https://gitlab.com/oauth-xx/version_gem/-/issues/3 + # Hence, only enable signing if `SKIP_GEM_SIGNING` is not set in ENV. + # See CONTRIBUTING.md + unless ENV.include?("SKIP_GEM_SIGNING") + user_cert = "certs/#{ENV.fetch("GEM_CERT_USER", ENV["USER"])}.pem" + cert_file_path = File.join(__dir__, user_cert) + cert_chain = cert_file_path.split(",") + cert_chain.select! { |fp| File.exist?(fp) } + if cert_file_path && cert_chain.any? + spec.cert_chain = cert_chain + if $PROGRAM_NAME.end_with?("gem") && ARGV[0] == "build" + spec.signing_key = File.join(Gem.user_home, ".ssh", "gem-private_key.pem") + end + end + end + spec.summary = "Find out what your Ruby gems are worth" - spec.description = 'Appraisal integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."' + spec.description = 'Appraisal2 integrates with bundler and rake to test your library against different versions of dependencies in repeatable scenarios called "appraisals."' + gh_mirror = "https://github.com/appraisal-rb/#{spec.name}" + gl_homepage = "https://gitlab.com/appraisal-rb/#{spec.name}" + spec.homepage = gl_homepage spec.license = "MIT" + spec.required_ruby_version = ">= 1.8.7" + + spec.metadata["homepage_uri"] = "https://#{spec.name}.galtzo.com/" + spec.metadata["source_code_uri"] = "#{gh_mirror}/releases/tag/v#{spec.version}" + spec.metadata["changelog_uri"] = "#{gl_homepage}/-/blob/v#{spec.version}/CHANGELOG.md" + spec.metadata["bug_tracker_uri"] = "#{gl_homepage}/-/issues" + spec.metadata["documentation_uri"] = "https://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" + spec.metadata["wiki_uri"] = "#{gl_homepage}/-/wiki" + spec.metadata["funding_uri"] = "https://github.com/sponsors/pboling" + spec.metadata["news_uri"] = "https://www.railsbling.com/tags/#{spec.name}" + spec.metadata["discord_uri"] = "https://discord.gg/3qme4XHNKN" + spec.metadata["rubygems_mfa_required"] = "true" # Specify which files are part of the released package. spec.files = Dir[ From fc591d172c483346ef906c03d024116e74da8f62 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:03:28 +0000 Subject: [PATCH 45/60] =?UTF-8?q?=F0=9F=91=B7=20Improve=20build=20on=20Git?= =?UTF-8?q?Lab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Parse results as JUnit --- .github/workflows/coverage.yml | 2 +- .gitlab-ci.yml | 99 ++++++++++++++++++++++++++++++++++ .idea/appraisal2.iml | 71 +++++++++++++++++++++++- .rspec | 4 ++ Gemfile.lock | 9 +++- appraisal2.gemspec | 28 ++++++++-- 6 files changed, 204 insertions(+), 9 deletions(-) create mode 100755 .gitlab-ci.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 91f1a2be..c774abd1 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -12,7 +12,7 @@ env: K_SOUP_COV_MIN_BRANCH: 85 K_SOUP_COV_MIN_LINE: 91 K_SOUP_COV_MIN_HARD: true - K_SOUP_COV_FORMATTERS: "html,xml,rcov,lcov,json,tty" + K_SOUP_COV_FORMATTERS: "xml,rcov,lcov,json,tty" K_SOUP_COV_DO: true K_SOUP_COV_MULTI_FORMATTERS: true K_SOUP_COV_COMMAND_NAME: "Test Coverage" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100755 index 00000000..fcc9b5c5 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,99 @@ +# You can override the included template(s) by including variable overrides +# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings +# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings +# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings +# Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings +# Note that environment variables can be set in several places +# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence +#stages: +# - test +#sast: +# stage: test +#include: +# - template: Security/SAST.gitlab-ci.yml + +variables: + BUNDLE_INSTALL_FLAGS: "--quiet --jobs=$(nproc) --retry=3" + K_SOUP_COV_DEBUG: true + K_SOUP_COV_DO: false + K_SOUP_COV_HARD: true + K_SOUP_COV_MIN_BRANCH: 85 + K_SOUP_COV_MIN_LINE: 91 + K_SOUP_COV_VERBOSE: true + K_SOUP_COV_FORMATTERS: "xml,rcov,lcov,json,tty" + K_SOUP_COV_MULTI_FORMATTERS: true + K_SOUP_COV_COMMAND_NAME: "Test Coverage" + +workflow: + rules: + # For merge requests, create a pipeline. + - if: '$CI_MERGE_REQUEST_IID' + # For default branch, create a pipeline (this includes on schedules, pushes, merges, etc.). + - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' + # For tags, create a pipeline. + - if: '$CI_COMMIT_TAG' + +default: + image: ruby:${RUBY_VERSION} + cache: + key: ${CI_JOB_IMAGE} + paths: + - vendor/ruby + artifacts: + reports: + junit: results/test_results.xml + +.test_template-current: &test_definition-current + stage: test + script: + - gem update --silent --system + - bundle config --local path vendor + - bundle install + - bin/rake + +.test_template-legacy: &test_definition-legacy + stage: test + script: + # Because we support EOL Ruby still... + - gem install rubygems-update -v ${RUBYGEMS_VERSION} + # Actually updates both RubyGems and Bundler! + - update_rubygems + - bundle config --local path vendor + - bundle install + - bundle exec rake test + +ruby-current: + variables: + BUNDLE_GEMFILE: gemfiles/current.gemfile + K_SOUP_COV_DO: true + <<: *test_definition-current + parallel: + matrix: + - RUBY_VERSION: ["3.2", "3.3", "3.4"] + +ruby-ruby3_1: + variables: + RUBYGEMS_VERSION: "3.6.9" + BUNDLE_GEMFILE: gemfiles/ruby_3_1.gemfile + <<: *test_definition-legacy + parallel: + matrix: + - RUBY_VERSION: ["3.1"] + +ruby-ruby3_0: + variables: + RUBYGEMS_VERSION: "3.5.23" + BUNDLE_GEMFILE: gemfiles/ruby_3_0.gemfile + <<: *test_definition-legacy + parallel: + matrix: + - RUBY_VERSION: ["3.0"] + +ruby-ruby2_7: + variables: + RUBYGEMS_VERSION: "3.4.22" + BUNDLE_GEMFILE: gemfiles/ruby_2_7.gemfile + <<: *test_definition-legacy + parallel: + matrix: + - RUBY_VERSION: ["2.7"] diff --git a/.idea/appraisal2.iml b/.idea/appraisal2.iml index cff17612..7ec75fc5 100644 --- a/.idea/appraisal2.iml +++ b/.idea/appraisal2.iml @@ -11,7 +11,7 @@ - + @@ -1787,6 +1787,36 @@ + + + + + + + + + + + + + + + @@ -2759,6 +2789,43 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -3191,6 +3258,6 @@ - + \ No newline at end of file diff --git a/.rspec b/.rspec index 78b7894f..95454248 100644 --- a/.rspec +++ b/.rspec @@ -2,3 +2,7 @@ --color --require spec_helper --warnings +--format html +--out results/test_results.html +--format RspecJunitFormatter +--out results/test_results.xml \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index b1a5d2e2..026df860 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -158,6 +158,8 @@ GEM ruby_engine (~> 2.0) ruby_version (~> 1.0) rspec-support (3.13.4) + rspec_junit_formatter (0.6.0) + rspec-core (>= 2, < 4, != 2.12.0) rubocop (1.75.8) json (~> 2.3) language_server-protocol (~> 3.17.0.2) @@ -253,6 +255,8 @@ GEM standard-custom (>= 1.0.2, < 2) standard-performance (>= 1.3.1, < 2) version_gem (>= 1.1.4, < 3) + stone_checksums (1.0.0) + version_gem (>= 1.1.5, < 3) stringio (3.1.7) terminal-table (4.0.0) unicode-display_width (>= 1.1.1, < 4) @@ -288,17 +292,20 @@ DEPENDENCIES kramdown (~> 2.5, >= 2.5.1) kramdown-parser-gfm (~> 1.1) logger (~> 1.7) + rake (~> 13.0) rdoc (~> 6.11) reek (~> 6.4) rspec (~> 3.13) rspec-block_is_expected (~> 1.0, >= 1.0.6) rspec-pending_for (~> 0.1, >= 0.1.17) + rspec_junit_formatter (~> 0.6) rubocop (~> 1.73, >= 1.73.2) rubocop-lts (~> 0.1, >= 0.1.1) rubocop-minitest (~> 0.36) rubocop-packaging (~> 0.6, >= 0.6.0) rubocop-rspec (~> 3.2) standard (~> 1.47) + stone_checksums (~> 1.0) thor (~> 1.3.2) uri (~> 1.0, >= 1.0.3) yard (~> 0.9, >= 0.9.37) @@ -306,4 +313,4 @@ DEPENDENCIES yard-relative_markdown_links (~> 0.5.0) BUNDLED WITH - 2.6.9 + 2.7.0 diff --git a/appraisal2.gemspec b/appraisal2.gemspec index a229249f..62889eb3 100644 --- a/appraisal2.gemspec +++ b/appraisal2.gemspec @@ -94,14 +94,32 @@ Gem::Specification.new do |spec| "appraisal", ] - spec.required_ruby_version = ">= 1.8.7" - spec.add_dependency("bundler", ">= 1.17.3") # Last version supporting Ruby 1.8.7 spec.add_dependency("rake", ">= 10") # Last version supporting Ruby 1.8.7 spec.add_dependency("thor", ">= 0.14") # Last version supporting Ruby 1.8.7 && Rails 3 + # NOTE: It is preferable to list development dependencies in the gemspec due to increased + # visibility and discoverability on RubyGems.org. + # However, development dependencies in gemspec will install on + # all versions of Ruby that will run in CI. + # This gem, and its runtime dependencies, will install on Ruby down to 1.8.7. + # This gem, and its development dependencies, will install on Ruby down to 2.3.x. + # This is because in CI easy installation of Ruby, via setup-ruby, is for >= 2.3. + # Thus, dev dependencies in gemspec must have + # + # required_ruby_version ">= 2.3" (or lower) + # + # Development dependencies that require strictly newer Ruby versions should be in a "gemfile", + # and preferably a modular one (see gemfiles/modular/*.gemfile). + + # Release Tasks + spec.add_development_dependency("rake", "~> 13.0") # Ruby >= 2.3.0 + spec.add_development_dependency("stone_checksums", "~> 1.0") # Ruby >= 2.2.0 + + # Testing spec.add_development_dependency("activesupport", ">= 3.2.21") - spec.add_development_dependency("rspec", "~> 3.13") - spec.add_development_dependency("rspec-block_is_expected", "~> 1.0", ">= 1.0.6") - spec.add_development_dependency("rspec-pending_for", "~> 0.1", ">= 0.1.17") + spec.add_development_dependency("rspec", "~> 3.13") # Ruby >= 0 + spec.add_development_dependency("rspec-block_is_expected", "~> 1.0", ">= 1.0.6") # Ruby >= 1.8.7 + spec.add_development_dependency("rspec_junit_formatter", "~> 0.6") # Ruby >= 2.3.0, for GitLab Test Result Parsing + spec.add_development_dependency("rspec-pending_for", "~> 0.1", ">= 0.1.17") # Ruby >= 1.8.7 end From 37c4ff5e04269dd600cb70d17d3fb00b53a71a37 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:28:15 +0000 Subject: [PATCH 46/60] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F=20Improve=20compati?= =?UTF-8?q?bility=20with=20systems=20that=20have=20appraisal=20gem=20insta?= =?UTF-8?q?lled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/appraisal.rb | 7 +++---- lib/appraisal2.rb | 5 ++++- spec/spec_helper.rb | 3 +++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/appraisal.rb b/lib/appraisal.rb index 3f5c8aa5..fe532243 100644 --- a/lib/appraisal.rb +++ b/lib/appraisal.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "appraisal/version" -require "appraisal/task" - -Appraisal::Task.new +# :nocov: +require "appraisal2" +# :nocov: diff --git a/lib/appraisal2.rb b/lib/appraisal2.rb index 8e220d11..3f5c8aa5 100644 --- a/lib/appraisal2.rb +++ b/lib/appraisal2.rb @@ -1,3 +1,6 @@ # frozen_string_literal: true -require "appraisal" +require "appraisal/version" +require "appraisal/task" + +Appraisal::Task.new diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 13fce886..a9862b3f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -24,4 +24,7 @@ end # This library +require "appraisal2" + +# RSpec support that depends on this library require "support/acceptance_test_helpers" From 0a71535580c552ee84ab645745fcaf8e028b6344 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:28:47 +0000 Subject: [PATCH 47/60] =?UTF-8?q?=F0=9F=93=9D=20How=20to=20run=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTING.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3de4ceec..81f574ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,12 @@ to abide by the thoughtbot [code of conduct]. 1. Fork the repo. 2. Run the tests. We only take pull requests with passing tests, and it's great -to know that you have a clean slate: `bundle && rake` +to know that you have a clean slate. We use `act` to run the tests the same way they run in CI. +Because there are so many workflows, running `act` naked might grind your machine to a halt. +Instead you can run a single workflow like this: +```console +act -W '.github/workflows/ruby-3-3.yml' +``` 3. Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, we need From cf1a343639b5b22acafb6b5640baff93bbb5d7a8 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:29:17 +0000 Subject: [PATCH 48/60] =?UTF-8?q?=F0=9F=93=9D=20Tweaking=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3a031903..90057b03 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ Appraisal.*.gemfile.lock .rspec_status /coverage/ /spec/reports/ +/results/* # Documentation /.yardoc/ diff --git a/README.md b/README.md index 55f9cecd..346874dc 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ are used. Sharing Modular Gemfiles between Appraisals ------- -_New for version 3.0_ +_New in appraisal2_ (not possible in thoughtbot's appraisal) It is common for Appraisals to duplicate sets of gems, and sometimes it makes sense to DRY this up into a shared, modular, gemfile. From 2dd7d7c45a19aaf977d64dd2db7ad13565c8917d Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:31:07 +0000 Subject: [PATCH 49/60] =?UTF-8?q?=F0=9F=90=9B=20Fix=20reek,=20spec=20rake?= =?UTF-8?q?=20tasks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Rakefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index fc98ba26..f05f5532 100644 --- a/Rakefile +++ b/Rakefile @@ -44,7 +44,9 @@ begin require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) - defaults << "spec" + # Not adding to defaults, because the coverage task, + # which is in defaults outside CI, will run specs. + defaults << "spec" if Kettle::Soup::Cover::IS_CI rescue LoadError desc("spec task stub") task(:spec) do @@ -100,7 +102,7 @@ begin Reek::Rake::Task.new do |t| t.fail_on_error = true t.verbose = false - t.source_files = "{lib,test}/**/*.rb" + t.source_files = "{lib,spec}/**/*.rb" end defaults << "reek" unless is_gitlab rescue LoadError From 17fc10eb4be0caa3526fd2ec75b92e1c91647935 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:36:00 +0000 Subject: [PATCH 50/60] =?UTF-8?q?=F0=9F=93=9D=20CONTRIBUTING.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTING.md | 139 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 108 insertions(+), 31 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 81f574ea..4fbc534a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,47 +1,124 @@ # Contributing -We love pull requests from everyone. By participating in this project, you agree -to abide by the thoughtbot [code of conduct]. +Bug reports and pull requests are welcome on GitLab at [https://gitlab.com/appraisal-rb/appraisal2][🚎src-main] +. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to +the [code of conduct][🤝conduct]. -[code of conduct]: https://thoughtbot.com/open-source-code-of-conduct +To submit a patch, please fork the project and create a patch with tests. +Once you're happy with it send a pull request. -1. Fork the repo. +We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it. + +## You can help! + +Simply follow these instructions: + +1. Join the Discord: [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] +2. Fork the repository +3. Create your feature branch (`git checkout -b my-new-feature`) +4. Make some fixes. +5. Commit your changes (`git commit -am 'Added some feature'`) +6. Push to the branch (`git push origin my-new-feature`) +7. Make sure to add tests for it. This is important, so it doesn't break in a future release. +8. Run the at least one workflow of tests via `act`, e.g.,: +```console +act -W '.github/workflows/ruby-3-3.yml' +``` +NOTE: Because there are so many workflows, running `act` naked might grind your machine to a halt. +9. Create new Pull Request. +10. Announce it in the channel for this org in the [Discord][✉️discord-invite]! + +## The Reek List + +Take a look at the `reek` list which is the file called `REEK` and find something to improve. + +To refresh the `reek` list: + +```console +bundle exec reek > REEK +``` + +## Run Tests + +To run all tests -2. Run the tests. We only take pull requests with passing tests, and it's great -to know that you have a clean slate. We use `act` to run the tests the same way they run in CI. -Because there are so many workflows, running `act` naked might grind your machine to a halt. -Instead you can run a single workflow like this: ```console -act -W '.github/workflows/ruby-3-3.yml' +bundle exec rake test ``` -3. Add a test for your change. Only refactoring and documentation changes -require no new tests. If you are adding functionality or fixing a bug, we need -a test! +## Lint It + +Run all the default tasks, which includes running the gradually autocorrecting linter, `rubocop-gradual`. + +```console +bundle exec rake +``` + +Or just run the linter. + +```console +bundle exec rake rubocop_gradual:autocorrect +``` + +## Contributors + +Your picture could be here! + +[![Contributors][🖐contributors-img]][🖐contributors] + +Made with [contributors-img][🖐contrib-rocks]. -4. Make the test pass. +Also see GitLab Contributors: [https://gitlab.com/appraisal-rb/appraisal2/-/graphs/main][🚎contributors-gl] -5. Push to your fork and submit a pull request. +## For Maintainers -At this point you're waiting on us. We like to at least comment on, if not -accept, pull requests within three business days (and, typically, one business -day). We may suggest some changes or improvements or alternatives. +### One-time, Per-maintainer, Setup -Some things that will increase the chance that your pull request is accepted, -taken straight from the Ruby on Rails guide: +**IMPORTANT**: If you want to sign the build you create, +your public key for signing gems will need to be picked up by the line in the +`gemspec` defining the `spec.cert_chain` (check the relevant ENV variables there). +All releases to RubyGems.org will be signed. +See: [RubyGems Security Guide][🔒️rubygems-security-guide] -* Use Rails idioms and helpers -* Include tests that fail without your code, and pass with it -* Update the documentation, the surrounding one, examples elsewhere, guides, - whatever is affected by your contribution +NOTE: To build without signing the gem you must set `SKIP_GEM_SIGNING` to some value in your environment. -Syntax: +### To release a new version: -* Two spaces, no tabs. -* No trailing whitespace. Blank lines should not have any space. -* Prefer &&/|| over and/or. -* MyClass.my_method(my_arg) not my_method( my_arg ) or my_method my_arg. -* a = b and not a=b. -* Follow the conventions you see used in the source already. +1. Run `bin/setup && bin/rake` as a tests, coverage, & linting sanity check +2. Update the version number in `version.rb`, and ensure `CHANGELOG.md` reflects changes +3. Run `bin/setup && bin/rake` again as a secondary check, and to update `Gemfile.lock` +4. Run `git commit -am "🔖 Prepare release v"` to commit the changes +5. Run `git push` to trigger the final CI pipeline before release, & merge PRs + - NOTE: Remember to [check the build][🧪build]! +6. Run `export GIT_TRUNK_BRANCH_NAME="$(git remote show origin | grep 'HEAD branch' | cut -d ' ' -f5)" && echo $GIT_TRUNK_BRANCH_NAME` +7. Run `git checkout $GIT_TRUNK_BRANCH_NAME` +8. Run `git pull origin $GIT_TRUNK_BRANCH_NAME` to ensure you will release the latest trunk code +9. Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use same timestamp, and generate same checksums + - Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH` + - If the echo above has no output, then it didn't work. + - Note that you'll need the `zsh/datetime` module, if running `zsh`. + - In older versions of `bash` you can use `date +%s` instead, i.e. `export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH` +10. Run `bundle exec rake build` +11. Run `bin/gem_checksums` (more context [1][🔒️rubygems-checksums-pr], [2][🔒️rubygems-guides-pr]) + to create SHA-256 and SHA-512 checksums. This functionality is provided by the `stone_checksums` + [gem][💎stone_checksums]. + - Checksums will be committed automatically by the script, but not pushed +12. Run `bundle exec rake release` which will create a git tag for the version, + push git commits and tags, and push the `.gem` file to [rubygems.org][💎rubygems] -And in case we didn't emphasize it enough: we love tests! +[🚎src-main]: https://gitlab.com/appraisal-rb/appraisal2 +[🧪build]: https://github.com/appraisal-rb/appraisal2/actions +[🤝conduct]: https://gitlab.com/appraisal-rb/appraisal2/-/blob/main/CODE_OF_CONDUCT.md +[🖐contrib-rocks]: https://contrib.rocks +[🖐contributors]: https://github.com/appraisal-rb/appraisal2/graphs/contributors +[🚎contributors-gl]: https://gitlab.com/appraisal-rb/appraisal2/-/graphs/main +[🖐contributors-img]: https://contrib.rocks/image?repo=appraisal-rb/appraisal2 +[💎rubygems]: https://rubygems.org +[🔒️rubygems-security-guide]: https://guides.rubygems.org/security/#building-gems +[🔒️rubygems-checksums-pr]: https://github.com/rubygems/rubygems/pull/6022 +[🔒️rubygems-guides-pr]: https://github.com/rubygems/guides/pull/325 +[💎stone_checksums]: https://github.com/pboling/stone_checksums +[📗keep-changelog]: https://keepachangelog.com/en/1.0.0/ +[📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat +[✉️discord-invite]: https://discord.gg/3qme4XHNKN +[✉️discord-invite-img]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge From 85d5a22a15921c41a225a883bbcc1e8acde7b556 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:43:34 +0000 Subject: [PATCH 51/60] =?UTF-8?q?=F0=9F=9A=A8=20Config=20reek?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reek.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 reek.yml diff --git a/reek.yml b/reek.yml new file mode 100644 index 00000000..293fa964 --- /dev/null +++ b/reek.yml @@ -0,0 +1,6 @@ +exclude_paths: + - tmp/* + - vendor/* + - coverage/* + - results/* + - .bundle/* \ No newline at end of file From 919180a3496f6d258eac4595d5bf43a656363241 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:43:53 +0000 Subject: [PATCH 52/60] =?UTF-8?q?=F0=9F=93=84=20Update=20Copyright?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MIT-LICENSE => LICENSE.txt | 1 + 1 file changed, 1 insertion(+) rename MIT-LICENSE => LICENSE.txt (95%) diff --git a/MIT-LICENSE b/LICENSE.txt similarity index 95% rename from MIT-LICENSE rename to LICENSE.txt index 780e12be..5d4de2c9 100644 --- a/MIT-LICENSE +++ b/LICENSE.txt @@ -1,6 +1,7 @@ The MIT License Copyright (c) 2010-2013 thoughtbot, inc. +Copyright (c) 2024 - 2025 Peter H. Boling (Galtzo.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 0cce6df9832cec7f09b5e23f1368c1febe9aa4e3 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:44:33 +0000 Subject: [PATCH 53/60] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Upgrade=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/appraisal2.iml | 32 ++++++++++++++++---------------- Gemfile.lock | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.idea/appraisal2.iml b/.idea/appraisal2.iml index 7ec75fc5..e86155a9 100644 --- a/.idea/appraisal2.iml +++ b/.idea/appraisal2.iml @@ -1858,7 +1858,7 @@ - + - + - + @@ -2494,7 +2494,7 @@ - + - - - + + + - - - + + + - - + + diff --git a/Gemfile.lock b/Gemfile.lock index 026df860..ca04061d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -171,7 +171,7 @@ GEM rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.45.1) + rubocop-ast (1.46.0) parser (>= 3.3.7.2) prism (~> 1.4) rubocop-gradual (0.3.6) @@ -232,7 +232,7 @@ GEM ansi simplecov terminal-table - simplecov-html (0.13.1) + simplecov-html (0.13.2) simplecov-lcov (0.8.0) simplecov-rcov (0.3.7) simplecov (>= 0.4.1) From fe06a597266831ef5c66526f987de48cb5578a61 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:45:27 +0000 Subject: [PATCH 54/60] =?UTF-8?q?=F0=9F=93=9D=20Add=20CoC=20v2.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CODE_OF_CONDUCT.md | 135 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..6be4700a --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,135 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[![Contact BDFL][🚂bdfl-contact-img]][🚂bdfl-contact]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations +[🚂bdfl-contact]: http://www.railsbling.com/contact +[🚂bdfl-contact-img]: https://img.shields.io/badge/Contact-BDFL-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red From c1a8f43d4d404e76b78a0db5b602859454d9c496 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 16 Jul 2025 23:46:30 +0000 Subject: [PATCH 55/60] =?UTF-8?q?=F0=9F=93=9D=20CITATION.cff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CITATION.cff | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 CITATION.cff diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..4ee49c70 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,20 @@ +cff-version: 1.2.0 +title: appraisal2 +message: >- + If you use this work and you want to cite it, + then you can use the metadata from this file. +type: software +authors: + - given-names: Peter Hurn + family-names: Boling + email: peter@railsbling.com + affiliation: railsbling.com + orcid: 'https://orcid.org/0009-0008-8519-441X' +identifiers: + - type: url + value: 'https://github.com/appraisal-rb/appraisal2/' + description: appraisal2 +repository-code: 'https://github.com/appraisal-rb/appraisal2/' +abstract: >- + appraisal2 +license: See license file From 9f347ecd0c25afa6d174c6e30b844a22e306e77a Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 23 Jul 2025 03:54:17 +0000 Subject: [PATCH 56/60] =?UTF-8?q?=F0=9F=91=B7=20Mark=20failing=20HEADs=20a?= =?UTF-8?q?s=20experimental?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/heads.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/heads.yml b/.github/workflows/heads.yml index 14212a07..5dac2baa 100644 --- a/.github/workflows/heads.yml +++ b/.github/workflows/heads.yml @@ -46,6 +46,7 @@ jobs: exec_cmd: "rake test" rubygems: default bundler: default + experimental: true # # truffleruby-head - ruby: "truffleruby-head" @@ -53,6 +54,7 @@ jobs: exec_cmd: "rake test" rubygems: default bundler: default + experimental: true # jruby-head - ruby: "jruby-head" @@ -60,6 +62,7 @@ jobs: exec_cmd: "rake test" rubygems: default bundler: default + experimental: false steps: - name: Checkout From 094721ed069f25a582177707dd18945b710b283f Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 23 Jul 2025 03:54:35 +0000 Subject: [PATCH 57/60] =?UTF-8?q?=F0=9F=91=B7=20provide=20path=20to=20lcov?= =?UTF-8?q?=20for=20coveralls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/coverage.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c774abd1..e6798451 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -80,6 +80,8 @@ jobs: uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: ./coverage/coverage.lcov + - name: Upload coverage to QLTY if: ${{ !env.ACT }} From abcb239bcbe415e700377d51bfb04aa51a3f708d Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 23 Jul 2025 03:55:44 +0000 Subject: [PATCH 58/60] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20IDE?= =?UTF-8?q?=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/appraisal2.iml | 4 ++++ .idea/vcs.xml | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.idea/appraisal2.iml b/.idea/appraisal2.iml index e86155a9..5b33bfac 100644 --- a/.idea/appraisal2.iml +++ b/.idea/appraisal2.iml @@ -10,6 +10,10 @@ + + + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 1749f799..83067447 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -3,9 +3,5 @@ - - - - \ No newline at end of file From 2d667f9e1e41d975f3ded31d5e6ec374dd8c104d Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 23 Jul 2025 03:56:39 +0000 Subject: [PATCH 59/60] =?UTF-8?q?=F0=9F=93=8C=20Ruby=203.4.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/acceptance/bundle_without_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/acceptance/bundle_without_spec.rb b/spec/acceptance/bundle_without_spec.rb index 77c6989f..426f424b 100644 --- a/spec/acceptance/bundle_without_spec.rb +++ b/spec/acceptance/bundle_without_spec.rb @@ -7,7 +7,7 @@ # The spec suite itself runs in bundler, and then we further execute bundler within tests. # Somehow this spec passes on truffleruby *only*!! # For some reason it is not working on Ruby v3 - pending_for(:engine => "ruby", :versions => %w(3.0.7 3.1.7 3.2.8 3.3.8 3.4.4), :reason => reason) + pending_for(:engine => "ruby", :versions => %w(3.0.7 3.1.7 3.2.8 3.3.8 3.4.5), :reason => reason) # And only some versions of Ruby v2 pending_for(:engine => "ruby", :versions => %w(2.3.8 2.4.10 2.5.9), :reason => reason) pending_for(:engine => "jruby", :reason => reason) From ef7a5206e48b4f6b3a95311623b90d63dc2717ae Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Wed, 23 Jul 2025 05:06:48 +0000 Subject: [PATCH 60/60] =?UTF-8?q?=F0=9F=91=B7=20Improve=20CI=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/coverage.yml | 2 +- .idea/appraisal2.iml | 60 +++++++++++++++++----------------- Gemfile | 5 ++- Gemfile.lock | 20 ++++++------ Rakefile | 2 +- 5 files changed, 44 insertions(+), 45 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e6798451..5612ddf5 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -80,7 +80,7 @@ jobs: uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ./coverage/coverage.lcov + path-to-lcov: ./coverage/lcov.info - name: Upload coverage to QLTY diff --git a/.idea/appraisal2.iml b/.idea/appraisal2.iml index 5b33bfac..cc9dbf83 100644 --- a/.idea/appraisal2.iml +++ b/.idea/appraisal2.iml @@ -825,7 +825,7 @@ - + - - + + - - + + - + @@ -1096,7 +1096,7 @@ - + - - - - + + + + - - - - + + + + - - - + + + - + - - + + - - + + - + diff --git a/Gemfile b/Gemfile index 11c6047f..39745dc8 100644 --- a/Gemfile +++ b/Gemfile @@ -61,9 +61,6 @@ elsif current_ruby_version < Gem::Version.new("3.3") elsif current_ruby_version < Gem::Version.new("3.4") eval_gemfile("gemfiles/modular/ruby-3-3.gemfile") elsif current_minor_ruby.eql?(latest_ruby_version) - # Only runs on the latest Ruby - eval_gemfile("gemfiles/modular/current.gemfile") - if is_ci if ENV.fetch("DEP_HEADS", "false").casecmp("true") == 0 eval_gemfile("gemfiles/modular/dep_heads.gemfile") @@ -85,6 +82,8 @@ elsif current_minor_ruby.eql?(latest_ruby_version) eval_gemfile("gemfiles/modular/documentation.gemfile") ### Linting eval_gemfile("gemfiles/modular/style.gemfile") + + eval_gemfile("gemfiles/modular/current.gemfile") end elsif current_minor_ruby > latest_ruby_version eval_gemfile("gemfiles/modular/heads.gemfile") diff --git a/Gemfile.lock b/Gemfile.lock index ca04061d..3e70d476 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,7 +82,7 @@ GEM erb (5.0.2) i18n (1.14.7) concurrent-ruby (~> 1.0) - json (2.12.2) + json (2.13.0) kettle-soup-cover (1.0.10) simplecov (~> 0.22) simplecov-cobertura (~> 3.0) @@ -100,23 +100,23 @@ GEM lint_roller (1.1.0) logger (1.7.0) minitest (5.25.5) - nokogiri (1.18.8-aarch64-linux-gnu) + nokogiri (1.18.9-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.18.8-aarch64-linux-musl) + nokogiri (1.18.9-aarch64-linux-musl) racc (~> 1.4) - nokogiri (1.18.8-arm-linux-gnu) + nokogiri (1.18.9-arm-linux-gnu) racc (~> 1.4) - nokogiri (1.18.8-arm-linux-musl) + nokogiri (1.18.9-arm-linux-musl) racc (~> 1.4) - nokogiri (1.18.8-arm64-darwin) + nokogiri (1.18.9-arm64-darwin) racc (~> 1.4) - nokogiri (1.18.8-x86_64-darwin) + nokogiri (1.18.9-x86_64-darwin) racc (~> 1.4) - nokogiri (1.18.8-x86_64-linux-gnu) + nokogiri (1.18.9-x86_64-linux-gnu) racc (~> 1.4) - nokogiri (1.18.8-x86_64-linux-musl) + nokogiri (1.18.9-x86_64-linux-musl) racc (~> 1.4) - ostruct (0.6.2) + ostruct (0.6.3) parallel (1.27.0) parser (3.3.8.0) ast (~> 2.4.1) diff --git a/Rakefile b/Rakefile index f05f5532..12dbf48a 100644 --- a/Rakefile +++ b/Rakefile @@ -46,7 +46,7 @@ begin RSpec::Core::RakeTask.new(:spec) # Not adding to defaults, because the coverage task, # which is in defaults outside CI, will run specs. - defaults << "spec" if Kettle::Soup::Cover::IS_CI + defaults << "spec" if !defined?(Kettle::Soup::Cover::IS_CI) || Kettle::Soup::Cover::IS_CI rescue LoadError desc("spec task stub") task(:spec) do