From 578fa6ef361b96faba4e667e4720283ec95111f0 Mon Sep 17 00:00:00 2001 From: Marie Ingabire <2383244+mingabire@users.noreply.github.com> Date: Tue, 8 Apr 2025 15:39:19 +0200 Subject: [PATCH 1/3] Upgrade to activerecord 8 * Replaces deprecated Codecov simplecov formatter with cobertura * Adopts the new rubocop syntax * Instruments services using ActiveSupport::Notifications * Upgrades ActiveRecord and related dependencies --- .github/workflows/ci.yml | 6 +- .rubocop.yml | 2 +- .ruby-version | 2 +- Gemfile | 18 ++-- Gemfile.lock | 148 ++++++++++++++++--------------- bin/rspec | 5 ++ lib/light/services/base.rb | 30 ++++--- lib/light/services/items/step.rb | 17 ++-- spec/data/models/order.rb | 2 +- spec/spec_helper.rb | 4 +- 10 files changed, 124 insertions(+), 110 deletions(-) create mode 100755 bin/rspec diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4eb1bb8..d1d437c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby: [3.0, 3.1, 3.2, 3.3, head, debug] + ruby: [3.0, 3.1, 3.2, 3.3, 3.4, head, debug] steps: - name: Git Checkout uses: actions/checkout@v2 @@ -43,7 +43,7 @@ jobs: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} steps: - name: Git Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install dependencies run: sudo apt-get install libsqlite3-dev @@ -58,6 +58,6 @@ jobs: run: bundle exec rspec - name: Code Coverage - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.rubocop.yml b/.rubocop.yml index 32abbc3..3a2bf5a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,4 +1,4 @@ -require: +plugins: - rubocop-rake - rubocop-rspec - rubocop-performance diff --git a/.ruby-version b/.ruby-version index bea438e..47b322c 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.1 +3.4.1 diff --git a/Gemfile b/Gemfile index 04ab0d1..caa7be6 100644 --- a/Gemfile +++ b/Gemfile @@ -5,17 +5,17 @@ source "https://rubygems.org" gemspec group :test do - gem "activerecord", "~> 7.1" - gem "database_cleaner-active_record", "~> 2.1" - gem "sqlite3", "~> 1.7" + gem "activerecord", "~> 8.0" + gem "database_cleaner-active_record", "~> 2.2" + gem "sqlite3", "~> 2.5" - gem "codecov", "~> 0.6.0" gem "rake", "~> 13.2" gem "rspec", "~> 3.13" - gem "simplecov", "~> 0.21" + gem "simplecov", "~> 0.22" + gem "simplecov-cobertura", "~> 2.1" - gem "rubocop", "~> 1.64", require: false - gem "rubocop-performance", "~> 1.21", require: false - gem "rubocop-rake", "~> 0.6", require: false - gem "rubocop-rspec", "~> 2.31", require: false + gem "rubocop", "~> 1.75", require: false + gem "rubocop-performance", "~> 1.25", require: false + gem "rubocop-rake", "~> 0.7", require: false + gem "rubocop-rspec", "~> 3.5", require: false end diff --git a/Gemfile.lock b/Gemfile.lock index e52b70b..cf2d1e9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,126 +6,130 @@ PATH GEM remote: https://rubygems.org/ specs: - activemodel (7.1.3.4) - activesupport (= 7.1.3.4) - activerecord (7.1.3.4) - activemodel (= 7.1.3.4) - activesupport (= 7.1.3.4) + activemodel (8.0.2) + activesupport (= 8.0.2) + activerecord (8.0.2) + activemodel (= 8.0.2) + activesupport (= 8.0.2) timeout (>= 0.4.0) - activesupport (7.1.3.4) + activesupport (8.0.2) base64 + benchmark (>= 0.3) bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) - ast (2.4.2) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + ast (2.4.3) base64 (0.2.0) - bigdecimal (3.1.8) - codecov (0.6.0) - simplecov (>= 0.15, < 0.22) - concurrent-ruby (1.3.3) - connection_pool (2.4.1) - database_cleaner-active_record (2.1.0) + benchmark (0.4.0) + bigdecimal (3.1.9) + concurrent-ruby (1.3.5) + connection_pool (2.5.0) + database_cleaner-active_record (2.2.0) activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) - diff-lcs (1.5.1) - docile (1.4.0) + diff-lcs (1.6.1) + docile (1.4.1) drb (2.2.1) - i18n (1.14.5) + i18n (1.14.7) concurrent-ruby (~> 1.0) - json (2.7.2) - language_server-protocol (3.17.0.3) - mini_portile2 (2.8.6) - minitest (5.23.1) - mutex_m (0.2.0) - parallel (1.25.1) - parser (3.3.2.0) + json (2.10.2) + language_server-protocol (3.17.0.4) + lint_roller (1.1.0) + logger (1.7.0) + mini_portile2 (2.8.8) + minitest (5.25.5) + parallel (1.26.3) + parser (3.3.7.4) ast (~> 2.4.1) racc - racc (1.8.0) + prism (1.4.0) + racc (1.8.1) rainbow (3.1.1) rake (13.2.1) - regexp_parser (2.9.2) - rexml (3.2.9) - strscan + regexp_parser (2.10.0) + rexml (3.4.1) rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) - rspec-core (3.13.0) + rspec-core (3.13.3) rspec-support (~> 3.13.0) - rspec-expectations (3.13.0) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.0) + rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-support (3.13.1) - rubocop (1.64.1) + rspec-support (3.13.2) + rubocop (1.75.2) json (~> 2.3) - language_server-protocol (>= 3.17.0) + 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 (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.31.1, < 2.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, < 3.0) - rubocop-ast (1.31.3) - parser (>= 3.3.1.0) - rubocop-capybara (2.21.0) - rubocop (~> 1.41) - rubocop-factory_bot (2.26.0) - rubocop (~> 1.41) - rubocop-performance (1.21.0) - rubocop (>= 1.48.1, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rake (0.6.0) - rubocop (~> 1.0) - rubocop-rspec (2.31.0) - rubocop (~> 1.40) - rubocop-capybara (~> 2.17) - rubocop-factory_bot (~> 2.22) - rubocop-rspec_rails (~> 2.28) - rubocop-rspec_rails (2.29.0) - rubocop (~> 1.40) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.44.0) + parser (>= 3.3.7.2) + prism (~> 1.4) + 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.5.0) + lint_roller (~> 1.1) + rubocop (~> 1.72, >= 1.72.1) ruby-progressbar (1.13.0) - simplecov (0.21.2) + securerandom (0.4.1) + simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-html (0.12.3) + simplecov-cobertura (2.1.0) + rexml + simplecov (~> 0.19) + simplecov-html (0.13.1) simplecov_json_formatter (0.1.4) - sqlite3 (1.7.3) + sqlite3 (2.6.0) mini_portile2 (~> 2.8.0) - strscan (3.1.0) - timeout (0.4.1) + timeout (0.4.3) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) + uri (1.0.3) PLATFORMS ruby DEPENDENCIES - activerecord (~> 7.1) - codecov (~> 0.6.0) + activerecord (~> 8.0) database_cleaner-active_record (~> 2.1) light-services! rake (~> 13.2) rspec (~> 3.13) - rubocop (~> 1.64) - rubocop-performance (~> 1.21) - rubocop-rake (~> 0.6) - rubocop-rspec (~> 2.31) - simplecov (~> 0.21) - sqlite3 (~> 1.7) + rubocop (~> 1.75) + rubocop-performance (~> 1.25) + rubocop-rake (~> 0.7) + rubocop-rspec (~> 3.5) + simplecov (~> 0.22) + simplecov-cobertura (~> 2.1) + sqlite3 (~> 2.5) BUNDLED WITH 2.5.10 diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 0000000..9da4c44 --- /dev/null +++ b/bin/rspec @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "rspec/core" +RSpec::Core::Runner.invoke diff --git a/lib/light/services/base.rb b/lib/light/services/base.rb index 87056f7..0cc46b5 100644 --- a/lib/light/services/base.rb +++ b/lib/light/services/base.rb @@ -74,24 +74,26 @@ def done? end def call - load_defaults_and_validate - log_header if benchmark? || verbose? + ActiveSupport::Notifications.instrument("call_service.light_services", { instance: self }) do + load_defaults_and_validate + log_header if benchmark? || verbose? - time = Benchmark.ms do - run_steps - run_steps_with_always + time = ActiveSupport::Benchmark.realtime(:float_millisecond) do + run_steps + run_steps_with_always - copy_warnings_to_parent_service - copy_errors_to_parent_service - end + copy_warnings_to_parent_service + copy_errors_to_parent_service + end - return unless benchmark + return unless benchmark - log "🟢 Finished #{self.class} in #{time}ms" - puts - rescue StandardError => e - run_steps_with_always - raise e + log "🟢 Finished #{self.class} in #{time}ms" + puts + rescue StandardError => e + run_steps_with_always + raise e + end end class << self diff --git a/lib/light/services/items/step.rb b/lib/light/services/items/step.rb index 33c2176..b042658 100644 --- a/lib/light/services/items/step.rb +++ b/lib/light/services/items/step.rb @@ -26,17 +26,20 @@ def run(instance, benchmark: false) return false unless run?(instance) if instance.respond_to?(name, true) - if benchmark - time = Benchmark.ms do + ActiveSupport::Notifications.instrument("run_step.light_services", + { instance: instance, step_name: name }) do + if benchmark + time = ActiveSupport::Benchmark.realtime(:float_millisecond) do + instance.send(name) + end + + instance.log "⏱️ Step #{name} took #{time}ms" + else instance.send(name) end - instance.log "⏱️ Step #{name} took #{time}ms" - else - instance.send(name) + true end - - true else raise Light::Services::NoStepError, "Cannot find step `#{name}` in service `#{@service_class}`" end diff --git a/spec/data/models/order.rb b/spec/data/models/order.rb index 4619148..4275c5b 100644 --- a/spec/data/models/order.rb +++ b/spec/data/models/order.rb @@ -11,7 +11,7 @@ class Order < ApplicationRecord validates :discount, numericality: { greater_than_or_equal: 0 } # Enumerables - enum status: { + enum :status, { in_progress: 1, completed: 2, canceled: 3 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index abd88ce..1abed90 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true require "simplecov" -require "codecov" +require "simplecov-cobertura" -SimpleCov.formatter = SimpleCov::Formatter::Codecov if ENV["CODECOV_TOKEN"] +SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter SimpleCov.start do add_filter "/spec/" add_filter "/example/" From af4c27a090cb7a5824bd22b0e12d67922cb0ce51 Mon Sep 17 00:00:00 2001 From: Marie Ingabire <2383244+mingabire@users.noreply.github.com> Date: Tue, 8 Apr 2025 15:53:50 +0200 Subject: [PATCH 2/3] Use the standard ruby benchmark module --- Gemfile.lock | 2 +- lib/light/services.rb | 2 ++ lib/light/services/base.rb | 2 +- lib/light/services/items/step.rb | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index cf2d1e9..b91e247 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -119,7 +119,7 @@ PLATFORMS DEPENDENCIES activerecord (~> 8.0) - database_cleaner-active_record (~> 2.1) + database_cleaner-active_record (~> 2.2) light-services! rake (~> 13.2) rspec (~> 3.13) diff --git a/lib/light/services.rb b/lib/light/services.rb index fc0fa7a..1b4dca9 100644 --- a/lib/light/services.rb +++ b/lib/light/services.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'benchmark' + require "light/services/config" require "light/services/version" require "light/services/exceptions" diff --git a/lib/light/services/base.rb b/lib/light/services/base.rb index 0cc46b5..fcce182 100644 --- a/lib/light/services/base.rb +++ b/lib/light/services/base.rb @@ -78,7 +78,7 @@ def call load_defaults_and_validate log_header if benchmark? || verbose? - time = ActiveSupport::Benchmark.realtime(:float_millisecond) do + time = Benchmark.realtime do run_steps run_steps_with_always diff --git a/lib/light/services/items/step.rb b/lib/light/services/items/step.rb index b042658..07a79a0 100644 --- a/lib/light/services/items/step.rb +++ b/lib/light/services/items/step.rb @@ -29,7 +29,7 @@ def run(instance, benchmark: false) ActiveSupport::Notifications.instrument("run_step.light_services", { instance: instance, step_name: name }) do if benchmark - time = ActiveSupport::Benchmark.realtime(:float_millisecond) do + time = Benchmark.realtime do instance.send(name) end From 682ce6c57a426e566e629479183b988e0e4b8a07 Mon Sep 17 00:00:00 2001 From: Marie Ingabire <2383244+mingabire@users.noreply.github.com> Date: Tue, 8 Apr 2025 16:25:36 +0200 Subject: [PATCH 3/3] CI: Removes ruby 3.0 and 3.1 from the test matrix. The older Ruby versions that are no longer actively supported --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1d437c..45af24c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,10 +19,10 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby: [3.0, 3.1, 3.2, 3.3, 3.4, head, debug] + ruby: [3.2, 3.3, 3.4, head, debug] steps: - name: Git Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install dependencies run: sudo apt-get install libsqlite3-dev