From 3e57eb531f2d028cb56cd1ddab9bb07c70b93abf Mon Sep 17 00:00:00 2001 From: Peter Goldstein Date: Thu, 27 Jan 2022 18:59:24 -0800 Subject: [PATCH] Add Ruby 3.1 to CI (#558) * Add Ruby 3.1 to CI Update Rubocop for recent Rubies Disable Rubocop run for Rubies before Ruby 2.4 Quote '3.0' in the CI configuration to ensure it loads a 3.0.x Ruby Set RUBYOPT="--disable_error_highlight" so Ruby 3.1 error matchers pass * Add CHANGELOG.md entry * Re-add deleted line from CHANGELOG.md * Set minimum supported Ruby version to 2.4. Remove a number of code bits designed to support Rubies below version 2.4 * Bump version. Remove unneeded require from Gemfile. Add require to spec/support file --- .github/workflows/main.yml | 16 ++++---- .rubocop.yml | 5 ++- CHANGELOG.md | 1 + Gemfile | 14 ++----- Guardfile | 2 + Rakefile | 3 ++ bin/console | 1 + hashie.gemspec | 2 + lib/hashie/extensions/coercion.rb | 9 +---- lib/hashie/mash.rb | 22 +++++----- lib/hashie/version.rb | 2 +- spec/hashie/array_spec.rb | 36 ++++++++--------- spec/hashie/extensions/coercion_spec.rb | 16 +------- spec/hashie/mash_spec.rb | 53 +++++++++++-------------- spec/integration/omniauth/Rakefile | 3 ++ spec/support/integration_specs.rb | 9 ++++- 16 files changed, 89 insertions(+), 105 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 55a3b9b..229eafc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -52,14 +52,12 @@ jobs: fail-fast: false matrix: ruby: - - 3.0 - - 2.7 - - 2.6 - - 2.5 - - 2.4 - - 2.3 - - 2.2 - - 2.1 + - '3.1' + - '3.0' + - '2.7' + - '2.6' + - '2.5' + - '2.4' steps: - uses: actions/checkout@v2 - name: Set up Ruby @@ -70,6 +68,8 @@ jobs: - name: Install dependencies run: bundle install --jobs 4 --retry 3 - name: Run tests + env: + RUBYOPT: "--disable-error_highlight" run: bundle exec rake test-jruby: diff --git a/.rubocop.yml b/.rubocop.yml index d35e18e..ced86ea 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -9,7 +9,7 @@ AllCops: inherit_from: .rubocop_todo.yml # Disabled until we can use the squiggly heredoc (after deprecating Ruby <2.3) -Layout/IndentHeredoc: +Layout/HeredocIndentation: Enabled: false Metrics/ClassLength: @@ -43,3 +43,6 @@ Naming/FileName: # boolean casting that we do. Style/DoubleNegation: Enabled: false + +Style/HashSyntax: + Enabled: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 2380f38..158736c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Any violations of this scheme are considered to be bugs. ### Changed * Your contribution here. +* [#558](https://github.com/hashie/hashie/pull/558): Test with Ruby 3.1 - [@petergoldstein](https://github.com/petergoldstein). ### Deprecated diff --git a/Gemfile b/Gemfile index 7edd0a4..283dc55 100644 --- a/Gemfile +++ b/Gemfile @@ -9,20 +9,12 @@ group :development do gem 'guard-rspec', '~> 4.3.1', require: false gem 'guard-yield', '~> 0.1.0', require: false gem 'pry' - gem 'pry-stack_explorer', platforms: %i[ruby_19 ruby_20 ruby_21] - gem 'rubocop', '0.52.1' + + gem 'rubocop', '~> 1.0' group :test do # ActiveSupport required to test compatibility with ActiveSupport Core Extensions. - # rubocop:disable Bundler/DuplicatedGem - require File.expand_path('../lib/hashie/extensions/ruby_version', __FILE__) - if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >= - Hashie::Extensions::RubyVersion.new('2.4.0') - gem 'activesupport', '~> 5.x', require: false - else - gem 'activesupport', '~> 4.x', require: false - end - # rubocop:enable Bundler/DuplicatedGem + gem 'activesupport', '~> 5.x', require: false gem 'rake' gem 'rspec', '~> 3' gem 'rspec-pending_for', '~> 0.1' diff --git a/Guardfile b/Guardfile index 4dfef8c..28fe7a6 100644 --- a/Guardfile +++ b/Guardfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative 'spec/support/integration_specs' run_all = lambda do |*| diff --git a/Rakefile b/Rakefile index 7544185..149696a 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rubygems' require 'bundler' Bundler.setup @@ -16,6 +18,7 @@ RuboCop::RakeTask.new(:rubocop) require_relative 'spec/support/integration_specs' task :integration_specs do next if ENV['CI'] + status_codes = [] handler = lambda do |status_code| status_codes << status_code unless status_code.zero? diff --git a/bin/console b/bin/console index 62d4bcd..e2cedcf 100755 --- a/bin/console +++ b/bin/console @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require 'bundler/setup' require 'hashie' diff --git a/hashie.gemspec b/hashie.gemspec index dbb438d..e7c061e 100644 --- a/hashie.gemspec +++ b/hashie.gemspec @@ -24,5 +24,7 @@ Gem::Specification.new do |gem| } end + gem.required_ruby_version = '>= 2.4' + gem.add_development_dependency 'bundler' end diff --git a/lib/hashie/extensions/coercion.rb b/lib/hashie/extensions/coercion.rb index a12490a..37d2d7c 100644 --- a/lib/hashie/extensions/coercion.rb +++ b/lib/hashie/extensions/coercion.rb @@ -17,14 +17,7 @@ module Hashie }.freeze ABSTRACT_CORE_TYPES = - if RubyVersion.new(RUBY_VERSION) >= RubyVersion.new('2.4.0') - { Numeric => [Integer, Float, Complex, Rational] } - else - { - Integer => [Fixnum, Bignum], - Numeric => [Fixnum, Bignum, Float, Complex, Rational] - } - end + { Numeric => [Integer, Float, Complex, Rational] } def self.included(base) base.send :include, InstanceMethods diff --git a/lib/hashie/mash.rb b/lib/hashie/mash.rb index d5cb308..21bcadb 100644 --- a/lib/hashie/mash.rb +++ b/lib/hashie/mash.rb @@ -322,22 +322,18 @@ module Hashie self.class.new(other_hash).merge(self) end - with_minimum_ruby('2.3.0') do - def dig(*keys) - super(*keys.map { |key| convert_key(key) }) - end + def dig(*keys) + super(*keys.map { |key| convert_key(key) }) end - with_minimum_ruby('2.4.0') do - def transform_values(&blk) - self.class.new(super(&blk)) - end + def transform_values(&blk) + self.class.new(super(&blk)) + end - # Returns a new instance of the class it was called on, with nil values - # removed. - def compact - self.class.new(super) - end + # Returns a new instance of the class it was called on, with nil values + # removed. + def compact + self.class.new(super) end with_minimum_ruby('2.5.0') do diff --git a/lib/hashie/version.rb b/lib/hashie/version.rb index 1c97af1..d19e3fe 100644 --- a/lib/hashie/version.rb +++ b/lib/hashie/version.rb @@ -1,3 +1,3 @@ module Hashie - VERSION = '5.0.1'.freeze + VERSION = '5.1.0'.freeze end diff --git a/spec/hashie/array_spec.rb b/spec/hashie/array_spec.rb index 0c35b1e..ee14a82 100644 --- a/spec/hashie/array_spec.rb +++ b/spec/hashie/array_spec.rb @@ -1,28 +1,26 @@ require 'spec_helper' describe Array do - with_minimum_ruby('2.3.0') do - describe '#dig' do - let(:array) { Hashie::Array.new(%i[a b c]) } + describe '#dig' do + let(:array) { Hashie::Array.new(%i[a b c]) } - it 'works with a string index' do - expect(array.dig('0')).to eq(:a) + it 'works with a string index' do + expect(array.dig('0')).to eq(:a) + end + + it 'works with a numeric index' do + expect(array.dig(1)).to eq(:b) + end + + context 'when array is empty' do + let(:array) { Hashie::Array.new([]) } + + it 'works with a first numeric and next string index' do + expect(array.dig(0, 'hello')).to eq(nil) end - it 'works with a numeric index' do - expect(array.dig(1)).to eq(:b) - end - - context 'when array is empty' do - let(:array) { Hashie::Array.new([]) } - - it 'works with a first numeric and next string index' do - expect(array.dig(0, 'hello')).to eq(nil) - end - - it 'throws an error with first string and next numeric index' do - expect { array.dig('hello', 0) }.to raise_error(TypeError) - end + it 'throws an error with first string and next numeric index' do + expect { array.dig('hello', 0) }.to raise_error(TypeError) end end end diff --git a/spec/hashie/extensions/coercion_spec.rb b/spec/hashie/extensions/coercion_spec.rb index 72265e1..9931ed4 100644 --- a/spec/hashie/extensions/coercion_spec.rb +++ b/spec/hashie/extensions/coercion_spec.rb @@ -563,13 +563,7 @@ describe Hashie::Extensions::Coercion do end it 'raises a CoercionError when coercion is not possible' do - type = - if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >= - Hashie::Extensions::RubyVersion.new('2.4.0') - Integer - else - Fixnum - end + type = Integer subject.coerce_value type, Symbol expect { instance[:hi] = 1 }.to raise_error( @@ -578,13 +572,7 @@ describe Hashie::Extensions::Coercion do end it 'coerces Integer to String' do - type = - if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >= - Hashie::Extensions::RubyVersion.new('2.4.0') - Integer - else - Fixnum - end + type = Integer subject.coerce_value type, String diff --git a/spec/hashie/mash_spec.rb b/spec/hashie/mash_spec.rb index 84a28ea..03f5668 100644 --- a/spec/hashie/mash_spec.rb +++ b/spec/hashie/mash_spec.rb @@ -649,8 +649,7 @@ describe Hashie::Mash do context 'when key does not exist' do it 'raises KeyError' do - error = RUBY_VERSION =~ /1.8/ ? IndexError : KeyError - expect { mash.fetch(:two) }.to raise_error(error) + expect { mash.fetch(:two) }.to raise_error(KeyError) end context 'with default value given' do @@ -980,44 +979,40 @@ describe Hashie::Mash do end end - with_minimum_ruby('2.3.0') do - describe '#dig' do - subject { described_class.new(a: { b: 1 }) } + describe '#dig' do + subject { described_class.new(a: { b: 1 }) } - it 'accepts both string and symbol as key' do - expect(subject.dig(:a, :b)).to eq(1) - expect(subject.dig('a', 'b')).to eq(1) - end + it 'accepts both string and symbol as key' do + expect(subject.dig(:a, :b)).to eq(1) + expect(subject.dig('a', 'b')).to eq(1) + end - context 'when the Mash wraps a Hashie::Array' do - it 'handles digging into an array' do - mash = described_class.new(alphabet: { first_three: Hashie::Array['a', 'b', 'c'] }) + context 'when the Mash wraps a Hashie::Array' do + it 'handles digging into an array' do + mash = described_class.new(alphabet: { first_three: Hashie::Array['a', 'b', 'c'] }) - expect(mash.dig(:alphabet, :first_three, 0)).to eq 'a' - end + expect(mash.dig(:alphabet, :first_three, 0)).to eq 'a' end end end - with_minimum_ruby('2.4.0') do - describe '#transform_values' do - subject(:mash) { described_class.new(a: 1) } + describe '#transform_values' do + subject(:mash) { described_class.new(a: 1) } - it 'returns a Hashie::Mash' do - expect(mash.transform_values(&:to_s)).to be_kind_of(described_class) - end + it 'returns a Hashie::Mash' do + expect(mash.transform_values(&:to_s)).to be_kind_of(described_class) + end - it 'transforms the value' do - expect(mash.transform_values(&:to_s).a).to eql('1') - end + it 'transforms the value' do + expect(mash.transform_values(&:to_s).a).to eql('1') + end - context 'when using with subclass' do - let(:subclass) { Class.new(Hashie::Mash) } - subject(:sub_mash) { subclass.new(a: 1).transform_values { |a| a + 2 } } + context 'when using with subclass' do + let(:subclass) { Class.new(Hashie::Mash) } + subject(:sub_mash) { subclass.new(a: 1).transform_values { |a| a + 2 } } - it 'creates an instance of subclass' do - expect(sub_mash).to be_kind_of(subclass) - end + it 'creates an instance of subclass' do + expect(sub_mash).to be_kind_of(subclass) end end diff --git a/spec/integration/omniauth/Rakefile b/spec/integration/omniauth/Rakefile index 9c220f7..c611f39 100644 --- a/spec/integration/omniauth/Rakefile +++ b/spec/integration/omniauth/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + namespace :perf do task :setup do require 'omniauth' @@ -12,6 +14,7 @@ namespace :perf do def call_app(path = ENV['GET_PATH'] || '/') result = @app.get(path) raise "Did not succeed #{result.body}" unless result.status == 200 + result end end diff --git a/spec/support/integration_specs.rb b/spec/support/integration_specs.rb index ea0da53..431167d 100644 --- a/spec/support/integration_specs.rb +++ b/spec/support/integration_specs.rb @@ -1,10 +1,17 @@ +require File.expand_path('../../../lib/hashie/extensions/ruby_version', __FILE__) + # Generates the bundle command for running an integration test # # @param [String] integration the integration folder to run # @param [String] command the command to run # @return [String] def integration_command(integration, command) - "#{integration_gemfile(integration)} #{command}" + if Hashie::Extensions::RubyVersion.new(RUBY_VERSION) >= + Hashie::Extensions::RubyVersion.new('3.1.0') + ruby_opts = "RUBYOPT=--disable-error_highlight " + end + + "#{ruby_opts}#{integration_gemfile(integration)} #{command}" end # Generates the Gemfile for an integration