[pull] master from ruby:master#844
Merged
pull[bot] merged 5 commits intoturkdevops:masterfrom Mar 12, 2026
Merged
Conversation
…ference: - ### Problem A gem that has a self-reference in its dependencies would previously get a warning during `gem build`, saying it's "discouradged". A gem that includes a self-reference can't be updated due to bundler filtering it out. https://github.com/ruby/rubygems/blob/6fd37f4afeb3943cf508d1394fcf4338a1266f2e/bundler/lib/bundler/resolver.rb#L405-L410 I think we should be more strict and prevent the gem from building. ### Solution Raise an explicit error. This codepath is only hit when running `gem build`, so this change won't affect existing consumers of those gems (it was previously possible to install those gems, but not update them, see ruby/rubygems#9346 for more context). ruby/rubygems@fa4673953a
- ### Problem
Bundler awaits for the dependencies of a gem to be download and installed
before it proceeds to downloading and installing the dependency itself.
This creates a bottleneck at the end of the installation process and
block a thread unnecessarily.
### Details
The installation strategy in Bundler is to await for "leaf gems" to
be download/installed before the "root gem" is processed.
For instance, in this scenario:
- Gem "foo" has a dependency on "bar" (We can call this the "root gem")
- Gem "bar" has no dependency (We call cal this the "leaf gems")
- A Gemfile adds "gem 'foo'"
In this case, only a single thread will have work to do, that is
because Bundler will queue the gem "bar" to be downloaded and
installed, and only when "bar" is finished, then Bundler will queue
work for "foo".
For **pure ruby gems**, this strategy is a waste of time because
during the installation, a gem's code is not evaluated and no
"require" statement is evaluated.
For gems with native extensions, this strategy make sense. When the
`extconf.rb` of a gem is evaluated, it's possible that the extconf
requires a dependency and therefore Bundler needs to wait for those
dependencies to be installed before it can execute the extconf.
A typical example is a native extension that require 'mini_portile2'.
### Solution
From the explanation above, I'd like to split the download from
the installation of a gem.
The tricky aspect is that there is no RubyGems API to know whether
a gem has a native extension. The only way to know is after we
download the gem and read the `metadata` from the tarball.
So the solution in this patch is as follow:
1. We download all gems without doing any checks.
2. Once the gems are downloaded, we now know whether a gem has a
native extensions.
3. If a gem is a pure ruby gems, we install it without waiting.
4. If a gem has a native extension, we check whether its dependencies
are installed. If a dependency is not yet installed, we put back
the gem in the queue. It will be dequeued later on and we'll redo
this logic.
### Performance gain
The speed gain highly depends on how deep the dependency tree is.
E.g. bar depends on foo which depends on baz which depends on jane ...
Previously we'd proceed to installing gems just one by one and only
a single thread would be used.
In a freshly generated Rails application, the speed gain is not that
important. And the reason is because we are having a "tail latency"
issue. Around the end of the installation process, the remaining
gems to be installed are the one with native extensions, since we
had to wait for for their dependencies to be installed. Compiling
them is the slowest part, and since we are doing it at the end then
the speed gain is not that noticeable.
### Misc
Another advantage of this change is to be able to more easily
implement this kind of feature ruby/rubygems#9138
to let users solely download gems, without installing them .
ruby/rubygems@e5e8c0a507
- There are failing tests on Ruby 3.2 due to an expecation that checks wheter stderr is empty. In this case, stderr outputs a warning from Ruby "warning: loading in progress, circular require considered harmful", but this is not true. This is a bug in Ruby 3.2 that I also encountered in ruby/rubygems#9100 (comment) The problem is that Ruby 3.2 wrongly output this warning when multiple threads try to require a file at the same time. See https://bugs.ruby-lang.org/issues/19415 which was fixed in Ruby 3.2.2. I opted to add a Mutex, as otherwise users on Ruby 3.2 will have this warning output. ruby/rubygems@713dd5c0e1
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )