Skip to content

chore(deps): state the Ruby floor, and watch unreleased Rails instead of capping - #10

Merged
thedumbtechguy merged 2 commits into
masterfrom
chore/dependency-bounds
Aug 17, 2026
Merged

chore(deps): state the Ruby floor, and watch unreleased Rails instead of capping#10
thedumbtechguy merged 2 commits into
masterfrom
chore/dependency-bounds

Conversation

@thedumbtechguy

Copy link
Copy Markdown
Contributor

Three changes, one decision behind them.

The actual bug

required_ruby_version said >= 2.3.0. Nothing could honour that: CI exercises Ruby 3.0–3.3, and activesupport 8 requires Ruby 3.2. A user on an older Ruby got a dependency-resolution failure that mentioned none of this.

It now says >= 3.0, matching what is tested.

No upper bound on activesupport is needed for that to hold. Bundler resolves a version suiting the running Ruby, so a Ruby 3.0 application lands on Rails 7.x without this gem having to say so.

Why the Rails deps stay unbounded

gem build warns about activesupport (>= 6) and actionpack (>= 6). That warning is now overridden knowingly, with the reasoning recorded in the gemspec rather than left for someone to rediscover.

A < N cap does not protect this gem from the next major — it decides where the breakage surfaces. Capping blocks every downstream application on the day that major ships, until this gem cuts a release. That is a cost everyone pays for a break that may never come.

Leaving it open moves the risk from install time to runtime, which is only defensible if somebody is watching.

What pays for that

A rails-main CI job that resolves against rails/rails main and runs the suite. Verified locally: it resolves to 8.1.0.alpha and the suite runs against it.

It is continue-on-error: true. A red run means Rails main changed something this gem relies on — a prompt to look, not a broken build. The point is finding out while the change is unreleased rather than from a bug report the week the major lands.

Its lockfile is gitignored on purpose. Committing one would pin the job to a revision and it would stop watching anything.

If that job is ever removed, the bounds should be revisited. The gemspec comment says so.

Not done

zeitwerk and phonelib are also unbounded and warn the same way. Left alone for consistency: one rule for dependencies, not one for Rails and another for everything else. Easy to revisit — they carry less blocking risk than the Rails gems, since they are not on a coordinated release train.

Verifying

bundle exec rake test → 1380 tests, 0 failures. gem build succeeds; the four warnings remain and are expected.

The interesting check is the new rails-main job on this PR: it is the first time this gem has been exercised against unreleased Rails.

required_ruby_version claimed ">= 2.3.0", which nothing here could honour:
CI exercises 3.0 to 3.3, and activesupport 8 requires Ruby 3.2. A user on
an older Ruby got a resolution failure that named none of that. It now
says ">= 3.0", matching what is actually tested. No upper bound is needed
on activesupport for that to hold - Bundler resolves a version suiting the
running Ruby, so a Ruby 3.0 application lands on Rails 7.x by itself.

The activesupport and actionpack dependencies stay unbounded above, and
RubyGems' warning about that is now overridden knowingly rather than
overlooked. A "< N" cap does not protect this gem from the next major; it
decides where the breakage surfaces. Capping blocks every downstream
application the day that major ships, until this gem cuts a release - a
cost everyone pays for a break that may never come.

Leaving it open moves that risk from install time to runtime, which is
only defensible if someone is watching. The rails-main CI job is that
watch: it resolves against rails/rails main and runs the suite, so an
incompatible change is found while still unreleased rather than in a bug
report the week it lands. It is allowed to fail, because a red run there
is a prompt to look rather than a broken build.

Its lockfile is gitignored deliberately. Committing one would pin the job
to a revision and it would stop watching anything.
The job failed on its first run, and not for the reason it exists to
report: `LoadError: cannot load such file -- standard/rake`. The gemfile
listed only `gemspec`, which brings the runtime dependencies, so rake,
minitest, standard and webmock were all absent and the suite could not
load its own Rakefile.

It evaluates the root Gemfile now, so the development dependencies come
with it and only the Rails version is overridden. Verified locally that
the evaluated gemfile does expose standard, minitest, rake and webmock.

Also moves the job to Ruby 3.4. Rails main already requires >= 3.3 through
ractor-dispatch, which is a genuine finding from that first run, and that
floor keeps rising - pinning this job to the minimum would fail it for a
Ruby version rather than for the API change it is watching for.
@thedumbtechguy
thedumbtechguy merged commit e16d045 into master Aug 17, 2026
6 checks passed
@thedumbtechguy
thedumbtechguy deleted the chore/dependency-bounds branch August 17, 2026 03:08
@thedumbtechguy thedumbtechguy changed the title State the Ruby floor, and watch unreleased Rails instead of capping chore(deps): state the Ruby floor, and watch unreleased Rails instead of capping Aug 17, 2026
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