diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index c2db24e..bd89a88 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -1,17 +1,13 @@ name: Danger -on: [pull_request] + +on: + pull_request: + types: [opened, reopened, edited, synchronize] + jobs: danger: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.7 - bundler-cache: true - - run: | - # Personal access token for dangerpr-bot - public, but base64 encoded to avoid tripping up GitHub - TOKEN=$(echo -n Z2hwX0xNQ3VmanBFeTBvYkZVTWh6NVNqVFFBOEUxU25abzBqRUVuaAo= | base64 --decode) - DANGER_GITHUB_API_TOKEN=$TOKEN bundle exec danger --verbose + uses: numbata/danger-pr-comment/.github/workflows/danger-run.yml@v0.1.0 + secrets: inherit + with: + ruby-version: '3.4' + bundler-cache: true diff --git a/.github/workflows/rubocop.yml b/.github/workflows/rubocop.yml index 9c3ec95..f0517c7 100644 --- a/.github/workflows/rubocop.yml +++ b/.github/workflows/rubocop.yml @@ -8,6 +8,6 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7 + ruby-version: '3.4' bundler-cache: true - run: bundle exec rubocop diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 838aecb..44be35e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,24 +9,20 @@ jobs: fail-fast: false matrix: entry: - - { ruby: '2.6.6', mongo: 'mongo:4.4', mongoid: '5' } + - { ruby: '3.1.7', mongo: 'mongo:4.4', mongoid: '5' } # - { ruby: 'jruby-9.1.17.0', mongo: 'mongo:4.4', mongoid: '5' } - { ruby: 'jruby-9.4.13.0', mongo: 'mongo:4.4', mongoid: '5' } - - { ruby: '2.6.6', mongo: 'mongo:4.4', mongoid: '6' } - - { ruby: '2.7.1', mongo: 'mongo:4.4', mongoid: '6' } - - { ruby: '3.0.5', mongo: 'mongo:4.4', mongoid: '6' } - - { ruby: '3.1.3', mongo: 'mongo:4.4', mongoid: '6' } + - { ruby: '3.1.7', mongo: 'mongo:4.4', mongoid: '6' } + - { ruby: '3.4.8', mongo: 'mongo:4.4', mongoid: '6' } - { ruby: 'jruby-9.4.13.0', mongo: 'mongo:4.4', mongoid: '6' } - - { ruby: '2.6.6', mongo: 'mongo:4.4', mongoid: '7', coverage: 'true' } - - { ruby: '2.7.1', mongo: 'mongo:4.4', mongoid: '7' } - - { ruby: '3.0.5', mongo: 'mongo:4.4', mongoid: '7' } - - { ruby: '3.1.3', mongo: 'mongo:4.4', mongoid: '7' } + - { ruby: '3.1.7', mongo: 'mongo:4.4', mongoid: '7', coverage: 'true' } + - { ruby: '3.4.8', mongo: 'mongo:4.4', mongoid: '7' } # - { ruby: 'jruby-9.4.13.0', mongo: 'mongo:4.4', mongoid: '7' } - - { ruby: '2.6.6', mongo: 'mongo:6.0', mongoid: '8' } - - { ruby: '2.7.1', mongo: 'mongo:7.0', mongoid: '8' } - - { ruby: '3.0.5', mongo: 'mongo:6.0', mongoid: '8' } - - { ruby: '3.1.3', mongo: 'mongo:7.0', mongoid: '8' } - - { ruby: '3.1.3', mongo: 'mongo:8.0', mongoid: '9' } + - { ruby: '3.1.7', mongo: 'mongo:6.0', mongoid: '8' } + - { ruby: '3.4.8', mongo: 'mongo:7.0', mongoid: '8' } + - { ruby: '3.4.8', mongo: 'mongo:8.0', mongoid: '9' } + - { ruby: '4.0.0', mongo: 'mongo:7.0', mongoid: '8' } + - { ruby: '4.0.0', mongo: 'mongo:8.0', mongoid: '9' } # - { ruby: 'jruby-9.4.13.0', mongo: 'mongo:8.0', mongoid: '8' } experimental: [false] diff --git a/.rspec b/.rspec index c99d2e7..775c62b 100644 --- a/.rspec +++ b/.rspec @@ -1 +1,2 @@ --require spec_helper +--format documentation \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml index 9637e2f..19bce00 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,7 @@ +AllCops: + SuggestExtensions: true + NewCops: enable + Lint/RaiseException: Enabled: true @@ -21,4 +25,6 @@ RSpec/LeakyConstantDeclaration: inherit_from: .rubocop_todo.yml -require: rubocop-rspec +plugins: + - rubocop-rspec + - rubocop-rake diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f7e101f..2751a13 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,54 +1,71 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2020-04-07 15:05:45 -0400 using RuboCop version 0.81.0. +# on 2025-12-31 23:55:39 UTC using RuboCop version 1.81.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 3 -# Configuration parameters: Include. -# Include: **/*.gemfile, **/Gemfile, **/gems.rb -Bundler/DuplicatedGem: +# Offense count: 1 +# Configuration parameters: Severity. +Gemspec/RequiredRubyVersion: Exclude: - - 'Gemfile' + - 'mongoid-locker.gemspec' -# Offense count: 4 -# Configuration parameters: IgnoredMethods. -Metrics/AbcSize: - Max: 24 +# Offense count: 6 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/support/configurations_shared_context.rb' + - 'spec/test_examples_spec.rb' -# Offense count: 11 -# Configuration parameters: CountComments, ExcludedMethods. -# ExcludedMethods: refine -Metrics/BlockLength: - Max: 290 +# Offense count: 8 +# Configuration parameters: AllowComments, AllowEmptyLambdas. +Lint/EmptyBlock: + Exclude: + - 'spec/support/locker_is_included_shared_examples.rb' -# Offense count: 5 -# Configuration parameters: CountComments, ExcludedMethods. +# Offense count: 3 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 27 + +# Offense count: 6 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: Max: 31 # Offense count: 1 -# Configuration parameters: CountComments. +# Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 105 + Max: 109 # Offense count: 2 -# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# CheckDefinitionPathHierarchyRoots: lib, spec, test, src # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS Naming/FileName: Exclude: + - 'Rakefile.rb' - 'lib/mongoid-locker.rb' - 'spec/mongoid-locker_spec.rb' # Offense count: 1 -# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros. -# NamePrefix: is_, has_, have_ -# ForbiddenPrefixes: is_, has_, have_ +# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates. +# AllowedMethods: call +# WaywardPredicates: nonzero? +Naming/PredicateMethod: + Exclude: + - 'lib/mongoid/locker/wrapper.rb' + +# Offense count: 1 +# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs. +# NamePrefix: is_, has_, have_, does_ +# ForbiddenPrefixes: is_, has_, have_, does_ # AllowedMethods: is_a? # MethodDefinitionMacros: define_method, define_singleton_method -Naming/PredicateName: +Naming/PredicatePrefix: Exclude: - 'spec/**/*' - 'lib/mongoid/locker.rb' @@ -56,28 +73,39 @@ Naming/PredicateName: # Offense count: 2 RSpec/BeforeAfterAll: Exclude: - - 'spec/spec_helper.rb' - - 'spec/rails_helper.rb' - - 'spec/support/**/*.rb' + - '**/spec/spec_helper.rb' + - '**/spec/rails_helper.rb' + - '**/spec/support/**/*.rb' - 'spec/test_examples_spec.rb' # Offense count: 1 +# Configuration parameters: IgnoredMetadata. RSpec/DescribeClass: Exclude: + - '**/spec/features/**/*' + - '**/spec/requests/**/*' + - '**/spec/routing/**/*' + - '**/spec/system/**/*' + - '**/spec/views/**/*' - 'spec/test_examples_spec.rb' -# Offense count: 8 -# Configuration parameters: Max. +# Offense count: 9 +# Configuration parameters: CountAsOne. RSpec/ExampleLength: + Max: 11 + +# Offense count: 5 +# This cop supports unsafe autocorrection (--autocorrect-all). +RSpec/IncludeExamples: Exclude: + - 'spec/mongoid-locker_spec.rb' - 'spec/support/locker_is_included_shared_examples.rb' - - 'spec/test_examples_spec.rb' + - 'spec/support/locker_methods_shared_examples.rb' -# Offense count: 1 -# Configuration parameters: CustomTransform, IgnoreMethods. -RSpec/FilePath: +# Offense count: 2 +RSpec/LetSetup: Exclude: - - 'spec/mongoid-locker_spec.rb' + - 'spec/support/populate_database_shared_context.rb' # Offense count: 12 # Configuration parameters: . @@ -85,30 +113,70 @@ RSpec/FilePath: RSpec/MessageSpies: EnforcedStyle: receive +# Offense count: 12 +# Configuration parameters: AllowSubject. +RSpec/MultipleMemoizedHelpers: + Max: 10 + +# Offense count: 2 +# Configuration parameters: AllowedPatterns. +# AllowedPatterns: ^expect_, ^assert_ +RSpec/NoExpectationExample: + Exclude: + - 'spec/support/locker_is_included_shared_examples.rb' + +# Offense count: 1 +RSpec/RemoveConst: + Exclude: + - 'spec/support/locker_helpers.rb' + +# Offense count: 1 +# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector. +# SupportedInflectors: default, active_support +RSpec/SpecFilePathFormat: + Exclude: + - '**/spec/routing/**/*' + - 'spec/mongoid-locker_spec.rb' + # Offense count: 1 RSpec/SubjectStub: Exclude: - 'spec/support/delegated_methods_shared_examples.rb' +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Style/CollectionQuerying: + Exclude: + - 'lib/mongoid/locker.rb' + # Offense count: 2 +# Configuration parameters: AllowedConstants. Style/Documentation: Exclude: - 'spec/**/*' - 'test/**/*' - 'lib/mongoid/locker.rb' +# Offense count: 4 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowSplatArgument. +Style/HashConversion: + Exclude: + - 'spec/support/locker_is_included_shared_examples.rb' + - 'spec/support/locker_methods_shared_examples.rb' + # Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods. +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # SupportedStyles: predicate, comparison Style/NumericPredicate: Exclude: - 'spec/**/*' - 'lib/mongoid/locker.rb' -# Offense count: 35 -# Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# Offense count: 7 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. # URISchemes: http, https Layout/LineLength: Max: 250 diff --git a/CHANGELOG.md b/CHANGELOG.md index 333ea05..bfe0d0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ ## Changelog -### 2.2.1 (Next) +### 2.3.0 (Next) +* [#109](https://github.com/mongoid/mongoid-locker/pull/109): Migrate Danger to use danger-pr-comment workflow - [@dblock](https://github.com/dblock). +* [#109](https://github.com/mongoid/mongoid-locker/pull/109): Remove support for Ruby 2.x - [@dblock](https://github.com/dblock). +* [#109](https://github.com/mongoid/mongoid-locker/pull/109): Add support for Ruby 4.0 - [@dblock](https://github.com/dblock). * Your contribution here. ### 2.2.0 (2025-06-22) diff --git a/Dangerfile b/Dangerfile index de2a4a0..f769387 100644 --- a/Dangerfile +++ b/Dangerfile @@ -1,3 +1,5 @@ # frozen_string_literal: true -danger.import_dangerfile(gem: 'mongoid-danger') +danger.import_dangerfile(gem: 'danger-pr-comment') + +changelog.check! diff --git a/Gemfile b/Gemfile index 5925a0f..238f213 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source 'https://rubygems.org' gemspec -case ENV['MONGOID_VERSION'] +case ENV.fetch('MONGOID_VERSION', nil) when /^9/ gem 'mongoid', '~> 9.0' when /^8/ @@ -27,11 +27,16 @@ end group :development, :test do gem 'pry-byebug', platforms: :mri + gem 'bigdecimal', '1.3.5', platforms: :mri + gem 'danger', require: false + gem 'danger-changelog', require: false + gem 'danger-pr-comment', require: false gem 'mongoid-compatibility' - gem 'mongoid-danger', '~> 0.2.0' gem 'mongoid-history' + gem 'mutex_m' gem 'rspec', '~> 3.9' - gem 'rubocop', '0.81.0' - gem 'rubocop-rspec', '1.38.1' + gem 'rubocop', '1.81.1' + gem 'rubocop-rake' + gem 'rubocop-rspec' gem 'simplecov', require: false end diff --git a/README.md b/README.md index 09f312b..82e9c01 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Document-level optimistic locking for MongoDB via Mongoid. Mongoid-Locker is an **NOTE:** Please refer to [1-x-stable](https://github.com/mongoid/mongoid-locker/tree/1-x-stable) branch for `1.x.x` documentation. See the [UPGRADING](UPGRADING.md) guide and [CHANGELOG](CHANGELOG.md) for an overview of the changes. [Tested](https://github.com/mongoid/mongoid-locker/actions) against: -- MRI: `2.3.8`, `2.4.7`, `2.5.7`, `2.6.6`, `2.7.1`, `3.0.5`, `3.1.3` +- MRI: `3.x`, `4.x` - JRuby `9.1.17.0`, `9.2.11.1` - Mongoid: `5`, `6`, `7`, `8`, `9` diff --git a/lib/mongoid/locker.rb b/lib/mongoid/locker.rb index 9f97d07..24be909 100644 --- a/lib/mongoid/locker.rb +++ b/lib/mongoid/locker.rb @@ -45,7 +45,7 @@ def secure_locking_name(_doc, opts) # @param opts [Hash] (see #with_lock) # @return [Float] def exponential_backoff(_doc, opts) - 2**opts[:attempt] + rand + (2**opts[:attempt]) + rand end # Returns time in seconds remaining to complete the lock of the provided document. Makes requests to the database. @@ -115,7 +115,9 @@ def included(klass) klass.locking_name_generator = locking_name_generator klass.delegate(*MODULE_METHODS, to: :class) - klass.singleton_class.delegate(*(methods(false) - MODULE_METHODS.flat_map { |method| [method, "#{method}=".to_sym] } - %i[included reset! configure]), to: self) + klass.singleton_class.delegate(*(methods(false) - MODULE_METHODS.flat_map do |method| + [method, :"#{method}="] + end - %i[included reset! configure]), to: self) end end @@ -202,7 +204,10 @@ def unlock_all # @param locking_name_generator [Symbol] def locker(**params) invalid_parameters = params.keys - Mongoid::Locker.singleton_class.const_get('MODULE_METHODS') - raise Mongoid::Locker::Errors::InvalidParameter.new(self.class, invalid_parameters.first) unless invalid_parameters.empty? + unless invalid_parameters.empty? + raise Mongoid::Locker::Errors::InvalidParameter.new(self.class, + invalid_parameters.first) + end params.each_pair do |key, value| send("#{key}=", value) @@ -271,7 +276,10 @@ def acquire_lock(opts) opts[:attempt] += 1 delay = self.class.send(backoff_algorithm, self, opts) - raise Errors::DocumentCouldNotGetLock.new(self.class, id) if delay >= maximum_backoff || opts[:attempt] >= opts[:retries] + if delay >= maximum_backoff || opts[:attempt] >= opts[:retries] + raise Errors::DocumentCouldNotGetLock.new(self.class, + id) + end sleep delay end diff --git a/lib/mongoid/locker/version.rb b/lib/mongoid/locker/version.rb index 4fd7d2b..bbf3150 100644 --- a/lib/mongoid/locker/version.rb +++ b/lib/mongoid/locker/version.rb @@ -2,6 +2,6 @@ module Mongoid module Locker - VERSION = '2.2.1' + VERSION = '2.3.0' end end diff --git a/mongoid-locker.gemspec b/mongoid-locker.gemspec index bdcfdcc..5760801 100644 --- a/mongoid-locker.gemspec +++ b/mongoid-locker.gemspec @@ -19,4 +19,5 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.add_dependency 'mongoid', '>= 5.0', '< 10' + s.metadata['rubygems_mfa_required'] = 'true' end diff --git a/spec/integration/mongoid-history/mongoid_history_spec.rb b/spec/integration/mongoid-history/mongoid_history_spec.rb index 7b0b006..e2f2cba 100644 --- a/spec/integration/mongoid-history/mongoid_history_spec.rb +++ b/spec/integration/mongoid-history/mongoid_history_spec.rb @@ -5,8 +5,7 @@ # This replicates the exception reported at https://github.com/mongoid/mongoid-history/issues/238#issuecomment-1063155193 # when mongoid-locker required 'forwardable' instead of relying on the # active support-provided delegation method -RSpec.describe 'MongoidHistory' do # rubocop:disable RSpec/DescribeClass - # rubocop:disable RSpec/ExampleLength +RSpec.describe 'MongoidHistory' do it 'does not raise an exception' do expect do Class.new do @@ -20,5 +19,4 @@ end end.not_to raise_exception end - # rubocop:enable RSpec/ExampleLength end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 17c4eb0..f3bc291 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,7 @@ ENV['RACK_ENV'] = 'test' require 'logger' # Required for compatibility with activesupport 7 +require 'bigdecimal' unless defined?(JRUBY_VERSION) if ENV['COVERAGE'] require 'simplecov'