Drop EOL Ruby and Rails from CI - #22
Merged
Merged
Conversation
Ruby 3.2 reached end of life on 2026-03-31 (endoflife.date/ruby), so CI no longer needs to prove the gem works there. Ruby 4.0 (eol 2029-03-31) takes its place alongside 3.3 (security-only until 2027-03-31) and 3.4. No exclude rules: every Ruby in the matrix runs against both gemfiles.
Rails 7.2 reached end of life on 2026-08-09 (endoflife.date/rails), so
the ActiveAdmin 3.5 leg now pins Rails 8.0. ActiveAdmin 3.5.2 resolves
and passes against it with the existing sprockets-rails / sassc-rails
stack and omniauth_openid_connect 0.6.1 — all four dummy-app suites are
green on Ruby 3.4.10.
The ActiveAdmin 4.0 leg stays on Rails 8.0 for now. Rails 8.1 is not
usable yet: railties 8.1 added `delegate_missing_to :@collection` to
Rails::Initializable::Collection but rails/initializable.rb only
requires "tsort", and rails/railtie.rb requires it before any
ActiveSupport core ext. This gem requires "rails/railtie" directly
(lib/activeadmin-oidc.rb) so loading it raises
NoMethodError: undefined method `delegate_missing_to`
for class Rails::Initializable::Collection
A bare `require "rails/railtie"` reproduces this with no ActiveAdmin in
the picture, and it does not happen on Rails 8.0.
Both pins stay three-segment on purpose: a two-segment `~> 8.0` means
>= 8.0, < 9.0 and would silently resolve to 8.1, so the leg would stop
testing the version it claims to.
Rails 8.0 goes EOL on 2026-11-07, so this needs a follow-up.
Ruby 3.2 went EOL on 2026-03-31 and is no longer in CI, so the gem no longer claims to support it. Ruby 3.3 is the new floor. The rails (>= 7.2, < 9) and activeadmin (>= 3.5, < 5) runtime constraints are deliberately untouched: dropping a Rails version from CI is not evidence the gem stopped working on it, and raising a runtime floor would be a breaking change for consumers.
Fivell
added a commit
that referenced
this pull request
Oct 1, 2026
Now that the gem loads on Rails 8.1 the AA 4.0 leg can test it. Rails 8.0 goes EOL on 2026-11-07 (endoflife.date/rails); 8.1 is supported until 2027-10-10, so this gives the repo a long-lived Rails leg. gemfiles/activeadmin_3.5.gemfile deliberately stays on "~> 8.0.0" so both currently supported Rails series are still covered. The pin stays three-segment: a two-segment "~> 8.1" would mean >= 8.1, < 9.0 and would drift onto 8.2 once that ships, so the leg would stop testing the version it names. Note on merge order: PR #22 adds a comment above this pin naming the Rails 8.1 blocker that this branch fixes. This branch is cut from main, where that comment does not exist yet. If #22 merges first, rebase and delete that now-stale comment.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Drops end-of-life Ruby and Rails from CI. The Ruby versions live in the workflow
matrix; the Rails version is pinned inside each gemfile under
gemfiles/, so thesubstantive part of this diff is there.
Source of truth for EOL dates: endoflife.date/ruby,
endoflife.date/rails.
Ruby matrix —
.github/workflows/ci.ymlruby['3.2', '3.3', '3.4']['3.3', '3.4', '4.0']No
exclude:rules were added — every Ruby runs against both gemfiles. Thegemfiledimension and the four per-dummy-app steps are unchanged.Rails pins —
gemfiles/gemfiles/activeadmin_3.5.gemfilerails "~> 7.2.0"rails "~> 8.0.0"gemfiles/activeadmin_4.0.gemfilerails "~> 8.0.0"rails "~> 8.0.0"(unchanged — see blocker)Rails 7.2 went EOL on 2026-08-09. ActiveAdmin 3.5.2 resolves and passes
against Rails 8.0 together with the existing
sprockets-rails/sassc-railsasset stack and
omniauth_openid_connect ~> 0.6.0— verified, see below.Pins stay three-segment on purpose. A two-segment
~> 8.0means>= 8.0, < 9.0and would silently resolve to 8.1, so the leg would stop testingthe version it claims to test.
This PR leaves the repo with no long-lived Rails leg. Both gemfiles now sit on
Rails 8.0, which reaches EOL on 2026-11-07 — about five weeks out. The intent
was to move
gemfiles/activeadmin_4.0.gemfileto~> 8.1.0(EOL 2027-10-10), butRails 8.1 currently cannot load this gem at all.
Root cause
railties 8.1 added
delegate_missing_to :@collectiontoRails::Initializable::Collection, butrails/initializable.rbonlyrequires"tsort"— it never requires the ActiveSupport core ext that definesdelegate_missing_to. Andrails/railtie.rbrequiresrails/initializablebefore any
active_support/core_ext. So a barerequire "rails/railtie"blowsup on Rails 8.1:
lib/activeadmin-oidc.rb:21does exactly thatrequire "rails/railtie",deliberately and with a comment, so that
omniauth/rails_csrf_protection's railtie loads for host apps.This is not an ActiveAdmin 4.0 / Propshaft / Tailwind problem. Minimal repro,
no ActiveAdmin in the picture:
railties 8.0.5.1's
initializable.rbdoes not usedelegate_missing_toat all,which is why 8.0 is unaffected.
Verified fix, deliberately not included here
Adding one line to
lib/activeadmin-oidc.rbbefore therails/railtierequire:makes the entire suite green on Rails 8.1.4 + ActiveAdmin 4.0.0.beta23 +
Propshaft/Tailwind (161 / 7 / 8 / 6 examples, 0 failures). I measured this and
then reverted it: this PR is scoped to dropping EOL versions, and that line is a
change to shipped library load order, not to CI. It wants its own PR — and it is
worth noting that this is a live bug for consumers, not just a CI issue: the
gemspec allows
rails >= 7.2, < 9, so any host app on Rails 8.1 that requiresthis gem crashes today.
Recommended follow-up, in order:
requiretolib/activeadmin-oidc.rb(fixes real Rails 8.1 consumers).gemfiles/activeadmin_4.0.gemfiletorails "~> 8.1.0"and drop thecomment this PR added above the pin.
Until then
gemfiles/activeadmin_4.0.gemfilecarries a comment naming the blocker.gemspec —
activeadmin-oidc.gemspecrequired_ruby_version">= 3.2.0"">= 3.3.0"Everything else is untouched on purpose:
rails (>= 7.2, < 9)andactiveadmin (>= 3.5, < 5)runtime constraints areunchanged. Dropping a version from CI is not evidence the gem stopped
working on it, and raising a runtime floor is a breaking change for consumers.
Is the
json < 3pin still needed?Yes — both pins and their comments are kept, unchanged.
json 3.0 removed the
quirks_modekeyword thatActiveSupport::JSONpasses toJSON.parse/JSON.generate. I checked the actual gem sources:quirks_modepassed?json/decoding.rb:23,json/encoding.rb:110json/decoding.rb:25,json/encoding.rb:110lib/So the pin is fixed as of Rails 8.1 — but since the Rails 8.1 blocker above
keeps both gemfiles on Rails 8.0, every CI leg still runs activesupport 8.0,
which still passes
quirks_mode. Removing the pin now would break the suite.It can be dropped from
gemfiles/activeadmin_4.0.gemfileas part of the Rails 8.1follow-up.
Other files checked, no change needed
.ruby-version—3.3.10, already at/above the new>= 3.3.0floor..rubocop.yml— does not exist, so there is noTargetRubyVersionto keep insync with
required_ruby_version, and RuboCop is not a CI step in this repo.README.md— no supported-versions table. Its one version mention ("Compatiblewith Rails 7.2+ and Rails 8's lazy route loading") describes the runtime
support range, which this PR does not change.
CHANGELOGin this repo, so none was created.Verification
Real local runs, every combination below.
CI=trueset throughout, each gemfilein its own
BUNDLE_PATH, all four dummy-app suites run separately exactly as CIinvokes them (
rake spec,rake spec:engine,rake spec:isolated,rake spec:root).All six combinations green, at the random seed each run picked for itself:
rake specspec:enginespec:isolatedspec:rootactiveadmin_3.5activeadmin_4.0activeadmin_3.5activeadmin_4.0activeadmin_3.5activeadmin_4.0bundle installexited 0 for all six.* The two Ruby 3.3.12
rake specruns initially came back with 2 and 1 failuresrespectively. That is a pre-existing, seed-dependent order dependency, not a
Ruby 3.3 problem — see the next section. The numbers above are from re-running
those two legs at
--seed 1.Resolved versions were identical across Rubies:
activeadmin_3.5.gemfile→ activeadmin 3.5.2, rails 8.0.5.1, sprockets-rails3.5.2, sassc-rails 2.1.2, omniauth_openid_connect 0.6.1, devise 5.0.4, json 2.21.2
activeadmin_4.0.gemfile→ activeadmin 4.0.0.beta23, rails 8.0.5.1, propshaft1.3.2, tailwindcss-rails 4.6.0, omniauth_openid_connect 0.8.0, devise 5.0.4, json 2.21.2
For reference, the pre-change baseline on Ruby 3.4.10 was also green
(
activeadmin_3.5.gemfileon Rails 7.2.3,activeadmin_4.0.gemfileon Rails8.0.5.1), so these numbers are a like-for-like comparison and not a suite that was
already red.
rake specon Rails 8 (~1 seed in 10)spec/spec_helper.rbsetsconfig.order = :randomwith a fresh seed per run, andthe default suite has an order dependency that only manifests on Rails 8. Two
examples are involved:
spec/unit/configuration_spec.rb:204— "#login_submit_path points at theOmniAuth entry point when stub login is off"
The expectation is built from the global
OmniAuth.config.path_prefix,while
login_submit_pathis derived from the gem's ownomniauth_path_prefix(lib/activeadmin/oidc/configuration.rb:193). Aslib/activeadmin/oidc/engine.rb:95already notes, Devise overwrites thatOmniAuth global at route-draw time — so under Rails 8 lazy route loading
the value this unit spec reads depends on whether some earlier request spec
has already triggered a route draw. Pure order dependency.
spec/requests/stub_login_spec.rb:229— "404s when the flag is flipped offafter the route was drawn" — gets a raised
ActionController::RoutingErrorinstead of a 404, again depending on route-draw timing.
Evidence that this is pre-existing and not introduced here — all on Ruby 3.4.10:
mainactiveadmin_4.0(untouched by this PR)mainactiveadmin_3.5activeadmin_3.5activeadmin_4.0And the failure tracks the seed, not the Ruby — same gemfile, same bundle:
A sweep of seeds 1–10 on this branch failed on seed 6 only, for both gemfiles
identically — roughly a 10% chance per run.
So:
main's ActiveAdmin 4.0 legs are already intermittently red today, becausethey already pin Rails 8.0. Rails 7.2 happened to mask the dependency on the 3.5
legs, so moving the 3.5 gemfile to Rails 8.0 widens this pre-existing exposure
from 3 CI legs to all 6. Expect occasional red runs on this PR and on
mainuntil the two specs are fixed. I left them alone deliberately — they are spec
hygiene, not EOL-version work, and fixing them here would bury the version diff
this PR is supposed to be reviewable as. Worth their own PR, alongside the Rails
8.1 fix above.
Ruby 3.3 patch choice
Ruby 3.3 was checked on 3.3.12, not 3.3.0: 3.3.0 is the single release with the
anonymous-parameter-forwarding-inside-a-block parser bug, which
ruby/setup-rubynever installs for
ruby-version: '3.3'(it picks the newest 3.3 patch). Nothingin this repo was changed to accommodate it.