Skip to content

Drop EOL Ruby and Rails from CI - #90

Merged
Fivell merged 2 commits into
masterfrom
chore/drop-eol-ruby-rails
Oct 1, 2026
Merged

Fivell merged 2 commits into
masterfrom
chore/drop-eol-ruby-rails

Conversation

@Fivell

@Fivell Fivell commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Drops end-of-life Ruby and Rails from CI and raises the gemspec Ruby floor to match. No gem version bump, no release.

Matrix: before / after

before after
ruby ['3.2', '3.3', '3.4'] ['3.3', '3.4', '4.0']
rails ['7.1.0', '7.2.0', '8.0.0'] ['8.0.0', '8.1.0']
activeadmin ['3.2.0', '3.3.0', '3.4.0', '3.5.1'] ['3.2.0', '3.3.0', '3.4.0', '3.5.1'] (unchanged)
exclude rails 8.0.0 x activeadmin 3.2.0 none
legs 35 24

Why these versions (endoflife.date)

Removed:

version EOL
Ruby 3.2 2026-03-31
Rails 7.1 2025-10-01
Rails 7.2 2026-08-09

Kept / added:

version EOL
Ruby 3.3 2027-03-31 (security-only; this is the floor)
Ruby 3.4 2028-03-31
Ruby 4.0 2029-03-31
Rails 8.0 2026-11-07 (oldest still supported)
Rails 8.1 2027-10-10

Rails 8.2 is not released (main is 8.2.0.alpha, no tag or pre-release), so it is not added.

ActiveAdmin versions dropped: none

Dropping Rails <= 7.2 can strand old ActiveAdmin versions that never supported Rails 8, so every AA entry was re-checked against both Rails 8.0 and 8.1 rather than assumed. All four resolve, install, and pass the full suite:

RAILS=8.0.0 AA=3.2.0 (resolved activeadmin 3.2.5) install=0  10 examples, 0 failures
RAILS=8.0.0 AA=3.3.0 (resolved activeadmin 3.3.0) install=0  10 examples, 0 failures
RAILS=8.0.0 AA=3.4.0 (resolved activeadmin 3.4.0) install=0  10 examples, 0 failures
RAILS=8.0.0 AA=3.5.1 (resolved activeadmin 3.5.2) install=0  10 examples, 0 failures
RAILS=8.1.0 AA=3.2.0 (resolved activeadmin 3.2.5) install=0  10 examples, 0 failures
RAILS=8.1.0 AA=3.3.0 (resolved activeadmin 3.3.0) install=0  10 examples, 0 failures
RAILS=8.1.0 AA=3.4.0 (resolved activeadmin 3.4.0) install=0  10 examples, 0 failures
RAILS=8.1.0 AA=3.5.1 (resolved activeadmin 3.5.2) install=0  10 examples, 0 failures

(Ruby 3.4.10, each leg with a freshly generated dummy app.)

So the existing

exclude:
  - rails: '8.0.0'
    activeadmin: '3.2.0'

is deleted, not carried over. It dates from before AA 3.2.x supported Rails 8; ~> 3.2.0 now resolves to activeadmin 3.2.5, which installs and goes 10/10 on both Rails 8.0 and 8.1. Keeping it would have silently skipped three working legs. bundle install never refused an AA version, so none was dropped and the activeadmin gemspec dependency stays ">= 3.0", "< 4.0".

The new matrix has no exclude: key at all.

On the Ruby 3.3 x Rails 8.1 cell: deliberately NOT excluded

This gem does pull actionview, so the known actionview 8.1 parse bug was in scope and was checked rather than assumed:

$ bundle list | grep actionview
  * actionview (8.1.4)
  * kaminari-actionview (1.2.2)

actionview 8.1.4 capture_helper.rb:50 forwards anonymous rest args inside a block, which is a SyntaxError on Ruby 3.3.0 — but only on 3.3.0, the very first 3.3 release. Later 3.3 patches lifted the parser restriction, and ruby/setup-ruby with ruby-version: '3.3' installs the newest 3.3 patch (3.3.12), so CI never sees it. Verified here, including the full suite on 3.3.12 x Rails 8.1:

ruby 3.3.12 / rails 8.1.0 / AA 3.5.1 : install=0  setup=0  10 examples, 0 failures

The same local-interpreter artifact showed up independently in simplecov: on Ruby 3.3.0, simplecov/result_merger/resultset_store.rb:38 (LOCK_MONITOR.synchronize { with_flock(&) }) fails to parse on every simplecov release tried — 1.2.0, 1.3.0, 1.3.1 and 1.3.2 — which is what rules out "a bad gem release" and confirms it is the 3.3.0 interpreter. simplecov 1.3.2 parses fine on 3.3.12 and 3.4.10. Accordingly no simplecov pin, no conditional gem "rails", RUBY_VERSION >= ... line, and no matrix exclude were added; nothing in the repo was changed to accommodate 3.3.0.

Rails 8.1 dummy-app fix (--skip-javascript)

Adding Rails 8.1 to the matrix surfaced a genuine failure in the dummy app, not a version-support problem. Rails 8.1's app template emits stale_when_importmap_changes in ApplicationController whenever importmap is in use, but the specs boot the dummy app under this gem's Gemfile, which has no importmap-rails:

NameError:
  undefined local variable or method 'stale_when_importmap_changes' for class ApplicationController
# ./spec/rails/rails-8.1.4/app/controllers/application_controller.rb:6

The dummy app's asset pipeline comes from sprockets-rails/sass-rails in the gem's Gemfile, so it never needed a JS bundler of its own. rails new ... --skip-javascript makes using_importmap? false and the line is no longer generated. Rails 8.0 legs are unaffected (its template has no such line) and stay green.

Local verification

Run on this machine with rbenv; CI=true is set because Rails 8's generated config/environments/test.rb has config.eager_load = ENV["CI"].present?, and ActiveAdmin needs the eager load for resource registration — without it the filter_form_spec examples 500 with undefined method 'values' for nil in batch_actions. That reproduces identically on unmodified master, on the Rails 8.0.0 / AA 3.5.1 leg CI already reports green, so it is a local-only artifact of this harness and not a regression from this PR.

Primary leg — Ruby 3.4.10 / Rails 8.1.0 / AA 3.5.1 (newest Rails in the matrix):

$ RBENV_VERSION=3.4.10 RAILS=8.1.0 AA=3.5.1 rbenv exec bundle install
Bundle complete! 12 Gemfile dependencies, 109 gems now installed.

$ RBENV_VERSION=3.4.10 RAILS=8.1.0 AA=3.5.1 rbenv exec bundle exec rake setup
setup=0

$ CI=true RBENV_VERSION=3.4.10 RAILS=8.1.0 AA=3.5.1 rbenv exec bundle exec rspec spec
..........

Finished in 16.48 seconds (files took 1.25 seconds to load)
10 examples, 0 failures

Line coverage: 64 / 67 (95.52%)

Corners:

leg bundle install rake setup rspec
Ruby 3.3.12 / Rails 8.0.0 / AA 3.2.0 (new floor) 0 0 10 examples, 0 failures
Ruby 3.3.12 / Rails 8.1.0 / AA 3.5.1 0 0 10 examples, 0 failures
Ruby 3.4.10 / Rails 8.1.0 / AA 3.5.1 0 0 10 examples, 0 failures
Ruby 4.0.6 / Rails 8.1.0 / AA 3.5.1 (new ceiling) 0 0 10 examples, 0 failures

Resolved versions on the ceiling leg: rails (8.1.4), actionview (8.1.4), activeadmin (3.5.2), simplecov (1.3.2).

Flake, locally: none. These are JS-heavy cuprite feature specs, but across roughly 20 local suite runs here no example flaked — every failure seen was deterministic and reproducible, and each was traced to a cause above (importmap, eager_load, or the 3.3.0 parser).

CI result

All 24/24 legs pass. deploy-coverage shows skipping, which is expected: it is gated on github.ref == 'refs/heads/master' && github.event_name == 'push'.

The first run had 23/24 with one failure on Ruby 4.0 / Rails 8.1.0 / AA 3.2.0, and it was the flake already documented in spec/support/capybara.rb rather than a real failure:

1) authors index edit form can set birthday
   Failure/Error: visit '/admin/authors/new'

   Ferrum::ProcessTimeoutError:
     Browser did not produce websocket url within 30 seconds, try to
     increase `:process_timeout`.

10 examples, 1 failure

9 of 10 examples passed in that leg; only the first one to launch Chrome died, and the job took 2m40s against ~1m50s for its siblings. That comment in capybara.rb says a rerun is currently the answer, so the job was rerun and passed in 57s with no code change. Flagging it because it is a pre-existing intermittent condition on GitHub runners that this PR neither causes nor fixes — expect the occasional rerun.

Coverage badge gating

Generate badge.json and Upload badge artifact moved from ruby 3.4 / rails 8.0.0 / AA 3.5.1 to ruby 4.0 / rails 8.1.0 / AA 3.5.1 — the newest cell in the new matrix. Checked against the parsed workflow so the badge is neither dropped nor duplicated:

total legs: 24
badge-gated legs: 1 -> [["4.0", "8.1.0", "3.5.1"]]
exclude key present: false

gemspec

required_ruby_version '>= 3.1.0' -> '>= 3.3'. Ruby 3.1 (EOL 2025-03-26) and 3.2 are no longer tested, so the old floor claimed untested support. Rails/activesupport dependency floors and the activeadmin dependency are left alone, and the gem version is unchanged.

There is no CHANGELOG in this repo, so none was created.

Nothing to change for .ruby-version, .rubocop.yml or the README: the repo has no .ruby-version and no .rubocop.yml (so no TargetRubyVersion to keep in sync with required_ruby_version), and the README has no badges or supported-versions table naming a Ruby or Rails version.

Fivell added 2 commits October 1, 2026 13:32
Ruby 3.2 reached EOL on 2026-03-31 and Rails 7.1 (2025-10-01) and
7.2 (2026-08-09) are both past EOL, so testing them no longer tells
us anything we act on. New matrix is a plain product:

  ruby:  ['3.3', '3.4', '4.0']
  rails: ['8.0.0', '8.1.0']

ActiveAdmin keeps all four entries. The old

  exclude:
    - rails: '8.0.0'
      activeadmin: '3.2.0'

is deleted rather than carried over: it dates from before AA 3.2.x
supported Rails 8, and `~> 3.2.0` now resolves to activeadmin 3.2.5,
which installs and passes the full suite on both Rails 8.0 and 8.1.
Nothing in the new matrix needs excluding, so the matrix has no
`exclude:` key at all.

The dummy app generator gains --skip-javascript. Rails 8.1's app
template emits `stale_when_importmap_changes` in ApplicationController
whenever importmap is in use, but the specs boot the dummy app under
*this gem's* Gemfile, which has no importmap-rails, so every example
died with:

  NameError: undefined local variable or method
  'stale_when_importmap_changes' for class ApplicationController

The dummy app's asset pipeline comes from sprockets-rails/sass-rails in
the gem's Gemfile, so it never needed a JS bundler of its own.

Coverage-badge steps now gate on ruby 4.0 / rails 8.1.0 / AA 3.5.1 --
the newest cell in the new matrix, and exactly 1 of the 24 legs, so
still exactly one badge artifact.

Gemfile's local default Rails drops to 8.0.0 for the same EOL reason;
CI always sets RAILS explicitly, so this only affects a bare `bundle`.
required_ruby_version was '>= 3.1.0', but Ruby 3.1 (EOL 2025-03-26)
and 3.2 (EOL 2026-03-31) are no longer in CI, so that floor claimed
support we do not test. 3.3 is the oldest Ruby the matrix exercises.

The activeadmin dependency stays at ">= 3.0", "< 4.0": no ActiveAdmin
version was dropped from the matrix (all four of 3.2.0, 3.3.0, 3.4.0
and 3.5.1 install and pass on Rails 8.0 and 8.1), and narrowing a
runtime floor would be a breaking change for consumers regardless.

No version bump and no release.
@Fivell
Fivell merged commit 8f8ccf8 into master Oct 1, 2026
49 of 50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant