From 1fdf7fbd91507ecb1fff574f9f6fceaa3feee29a Mon Sep 17 00:00:00 2001 From: Matt Menefee Date: Mon, 1 Jun 2026 18:26:06 -0500 Subject: [PATCH] Drop support for Ruby 3.2 and remove dead version guards Ruby 3.2 reached end-of-life on 2026-04-01 and no longer receives security patches. Continuing to advertise and test against an unsupported runtime provides little value and spends CI on a version no one should run in production. Raise the floor to Ruby 3.3 (currently in security maintenance, EOL expected 2027-03-31): - Bump `required_ruby_version` to `>= 3.3` - Drop `'3.2'` from the CI test matrix (3.3 was already covered) - Raise RuboCop `TargetRubyVersion` to 3.3 - Update the README compatibility statement and CONTRIBUTING prerequisites - Drop the `parser` / `prism` version conditional from the Witchcraft optional-dependency list in the troubleshooting guide, leaving `method_source` and `unparser` (Prism is bundled with Ruby 3.3+ and `parser` is pulled in transitively by `unparser`, so neither needs adding to a Gemfile) With the floor at 3.3, the version-conditional code becomes dead and is removed: - `Chewy::Index::Witchcraft` branched on `RUBY_VERSION >= '3.3'` to pick between Prism (a default gem since Ruby 3.3) and the external `parser` gem. The `parser` fallback in the requires, `check_requirements!` and `ast_from_proc` is now unreachable, so witchcraft always uses Prism (also removing a fragile string version comparison). The Prism requirements check is dropped too: Prism ships with Ruby 3.3+, so it is always present and never needs adding to a Gemfile, and the real `parser` dependency is already covered transitively by the `unparser` check. - `Chewy::LogSubscriber` branched on `ActiveSupport.version >= 7.1`, unconditionally true since the ActiveSupport >= 7.2 floor; the pre-7.1 positional `color` call is removed. This is a breaking change for anyone still on Ruby 3.2; they must upgrade to 3.3+ to use future Chewy releases. Version-anchored docs that describe past releases' requirements (e.g. the Chewy 7 to 8 migration guide) are intentionally left unchanged. --- .github/workflows/ruby.yml | 2 +- .rubocop.yml | 2 +- CHANGELOG.md | 2 ++ CONTRIBUTING.md | 2 +- README.md | 2 +- chewy.gemspec | 2 +- docs/troubleshooting.md | 2 +- lib/chewy/index/compiled.rb | 3 +-- lib/chewy/index/witchcraft.rb | 17 ++--------------- lib/chewy/log_subscriber.rb | 6 +----- 10 files changed, 12 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 8cecf5f74..9ffae93b8 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - ruby: [ '3.2', '3.3', '3.4', '4.0' ] + ruby: [ '3.3', '3.4', '4.0' ] gemfile: [rails.7.2.activerecord, rails.8.0.activerecord, rails.8.1.activerecord] name: ${{ matrix.ruby }}-${{ matrix.gemfile }} diff --git a/.rubocop.yml b/.rubocop.yml index b292bcb55..cd77e6575 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -5,7 +5,7 @@ plugins: AllCops: NewCops: enable - TargetRubyVersion: 3.2 + TargetRubyVersion: 3.3 SuggestExtensions: false Layout/AccessModifierIndentation: diff --git a/CHANGELOG.md b/CHANGELOG.md index 85a38efa8..e9f260377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### Changes +* [#1029](https://github.com/toptal/chewy/pull/1029): **(Breaking)** Drop support for Ruby 3.2, which reached end-of-life on 2026-04-01. Chewy now requires Ruby `>= 3.3`. ([@mattmenefee][]) + ## 8.4.1 (2026-06-19) ### New Features diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 720207d0f..2e06798c9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ do so. ### Prerequisites -- Ruby 3.2+ +- Ruby 3.3+ - Docker (for Elasticsearch) ### Starting Elasticsearch diff --git a/README.md b/README.md index 3686eb7dd..a48796c9b 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Chewy aims to support all Ruby and Rails versions that are currently maintained ### Ruby -Chewy is compatible with MRI 3.2-4.0. +Chewy is compatible with MRI 3.3-4.0. ### Elasticsearch compatibility matrix diff --git a/chewy.gemspec b/chewy.gemspec index 57aba4036..bc10abac4 100644 --- a/chewy.gemspec +++ b/chewy.gemspec @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| spec.description = 'Chewy provides functionality for Elasticsearch index handling, documents import mappings and chainable query DSL' spec.homepage = 'https://github.com/toptal/chewy' spec.license = 'MIT' - spec.required_ruby_version = '>= 3.2' + spec.required_ruby_version = '>= 3.3' spec.files = Dir['CHANGELOG.md', 'LICENSE.txt', 'README.md', 'lib/**/*'] spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 81f488a15..013e037f5 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -79,7 +79,7 @@ See [configuration.md](configuration.md#import-scope-clean-up-behavior) for deta Some Chewy features require additional gems that are not listed as hard dependencies: - **`parallel`** — required for `chewy:parallel:*` rake tasks. Install it with `gem 'parallel'` in your Gemfile. -- **`method_source`**, **`parser`** (or **`prism`** on Ruby 3.3+), **`unparser`** — required only for the deprecated `witchcraft!` path. Not needed for the default compiled compose path. Install them only if you still call `witchcraft!` from an index. +- **`method_source`** and **`unparser`** — required only for the deprecated `witchcraft!` path. Not needed for the default compiled compose path. Install them only if you still call `witchcraft!` from an index. If these gems are missing you'll get a `LoadError` when the relevant feature is used. diff --git a/lib/chewy/index/compiled.rb b/lib/chewy/index/compiled.rb index c143dfb3e..d426cd675 100644 --- a/lib/chewy/index/compiled.rb +++ b/lib/chewy/index/compiled.rb @@ -7,8 +7,7 @@ class Index # per-field arity into the call site and inlines hash construction, # removing the per-field iteration + dispatch overhead of the legacy # plain compose path. Proc bodies are NOT inlined — procs are called - # via `.call`. In exchange there are no parser/unparser/method_source - # deps and no Ruby/Prism version coupling. + # via `.call`. # # `fields:` selection is supported: a dedicated method is generated # and memoized per unique fields set. diff --git a/lib/chewy/index/witchcraft.rb b/lib/chewy/index/witchcraft.rb index 9b8da649f..622e93174 100644 --- a/lib/chewy/index/witchcraft.rb +++ b/lib/chewy/index/witchcraft.rb @@ -11,11 +11,7 @@ def self.load_dependencies! return if @dependencies_loaded require 'method_source' - begin - require 'prism' - rescue LoadError - require 'parser/current' - end + require 'prism' require 'unparser' @dependencies_loaded = true rescue LoadError @@ -38,11 +34,6 @@ def witchcraft! def check_requirements! messages = [] messages << "MethodSource gem is required for the Witchcraft, please add `gem 'method_source'` to your Gemfile" unless Proc.method_defined?(:source) - if RUBY_VERSION >= '3.3' - messages << "Prism gem is required for the Witchcraft, please add `gem 'prism'` to your Gemfile" unless '::Prism'.safe_constantize - else - messages << "Parser gem is required for the Witchcraft, please add `gem 'parser'` to your Gemfile" unless '::Parser'.safe_constantize - end messages << "Unparser gem is required for the Witchcraft, please add `gem 'unparser'` to your Gemfile" unless '::Unparser'.safe_constantize messages = messages.join("\n") @@ -211,11 +202,7 @@ def source_for(proc, nesting) # rubocop:disable Metrics/AbcSize end def ast_from_proc(proc) - if defined?(Prism) - Prism::Translation::ParserCurrent.parse(proc.source) - else - Parser::CurrentRuby.parse(proc.source) - end + Prism::Translation::ParserCurrent.parse(proc.source) end def extract_lambdas(node) diff --git a/lib/chewy/log_subscriber.rb b/lib/chewy/log_subscriber.rb index 368c0813b..d2042e177 100644 --- a/lib/chewy/log_subscriber.rb +++ b/lib/chewy/log_subscriber.rb @@ -24,11 +24,7 @@ def render_action(action, event) subject = payload[:type].presence || payload[:index] action = "#{subject} #{action} (#{event.duration.round(1)}ms)" - action = if ActiveSupport.version >= Gem::Version.new('7.1') - color(action, GREEN, bold: true) - else - color(action, GREEN, true) - end + action = color(action, GREEN, bold: true) debug(" #{action} #{description}") end