New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatically remove "ruby" from lockfile if incomplete #5807
Automatically remove "ruby" from lockfile if incomplete #5807
Conversation
d546d3e
to
f1c7842
Compare
f1c7842
to
69d0b4e
Compare
The latest versions of bundler has an issue where incomplete lockfiles that are locked to "ruby" but not including exclusively gems NOT platform specific. This causes an issue with existing lockfiles, generating a missing gem error. This is explained in more detail in: rubygems/rubygems#5807 Since this is currently preventing Dependabot updates for our users, especially around sorbet dependencies, and since we have no good way to signal these failures to them with an explanation on how to resolve it, I think it's best that we downgrade bundler to a version that does not include this, until rubygems/rubygems#5807 is merged and we can bump to the latest version again.
The latest versions of bundler has an issue where incomplete lockfiles that are locked to "ruby" but not including exclusively gems NOT platform specific. This causes an issue with existing lockfiles, generating a missing gem error. This is explained in more detail in: rubygems/rubygems#5807 Since this is currently preventing Dependabot updates for our users, especially around sorbet dependencies, and since we have no good way to signal these failures to them with an explanation on how to resolve it, I think it's best that we downgrade bundler to a version that does not include this, until rubygems/rubygems#5807 is merged and we can bump to the latest version again.
…ot-resolvable Automatically remove "ruby" from lockfile if incomplete (cherry picked from commit 839441c)
Apologies for jumping on an old PR like this, but this new behavior is causing us lots of problems. Context:
We recently updated bundler, and now it keeps trying to remove the |
Hi! Sorry, I just wanted to make things easier for users, because a Gemfile/Gemfile.lock files that were previously working, would suddenly would no longer work, and that seemed pretty bad. Bundler does this kind of sanitization in other places, for example if it finds redundant lockfile dependencies, or redundant platform specific gems in there, so this didn't seem bad. |
Bundles stacks record locking reset Thanks for the recovery deivid=rodriguez |
@deivid-rodriguez please don't apologize :) I dropped this message a bit quickly without much actionable content because I had to run, but I'd like to try to find a way forward.
What is interesting is that our current Gemfile/Gemfile.lock work perfectly on install, but whenever we update we lose the One of the root cause is that I searched a lot, but I couldn't find a proper workaround for this aside from manually editing the Gemfile.lock or downgrading bundler. Would you by any chance have some pointers to some potential features I could use to workaround this issue? I wish I could scope the |
I don't understand the issue very well. What is it broken without the ruby platform, which error do you get? |
On 3.1.2 it works fine. However when trying to bundle that same
But before we upgraded bundler, it would simply fail quickly complaining that some of our native gems require I know you've told me in the past that you don't support using the same I hope this description makes sense? I can try to generate a small repro, I think just nokogiri + sorbet in the same Gemfile should allow to repro. |
source "https://rubygems.org"
gem "sorbet"
gem "nokogiri"
So the pair above allows you to But if you run |
Ok, I think it should work without Ruby. I will have a look at what's going on. |
Hum, actually it works on my machine with that minimal example, there might be more to it in our big gemfile that cause bundler to spend over an hour resolving dependencies. I'll try to run it in debug mode see if there's more to it. |
Also 2.3.24 actually fixed some "bundler resolving forever" issues. Maybe you can try that too. |
Oh! Missed that there was a As for the debug build, no real smoking guns in the debug output I'm afraid, only:
But that's essentially what I was describing. |
Seems like |
Hum, I'll dig more tomorrow, but while this solved it on "CI", it fails when we build our production images. The only difference is that we pass
And I can't add |
That sounds like you're using |
It is (or was) yes. That's how we managed to keep bundling on We might no need it anymore with more recent bundlers? I'll try removing it. |
Yeah, I think we don't need it now that #5715 was fixed. |
Yes, |
Hum, no dice I'm afraid, if I remove the force ruby platform, I can't bundle anymore because I only have native versions of nokogiri in my gemfile:
|
I believe we discovered in an earlier issue (#4012) that a Gemfile.lock generated by one version of Ruby is not guaranteed to work with another version of Ruby. So if you generate with Ruby 3.1 it's not guaranteed to work with Ruby 3.2. Maybe @deivid-rodriguez can correct me if I'm misunderstanding the intended behavior. |
That's right, although if you do it the other way around it might work: generate it with Ruby 3.2, so that the version of nokogiri that's not platform specific is picked up. Alternatively, you can use |
Yes I remember. But until now we've always managed to find work arounds, and this "non-feature" is extremely valuable for us, so I'm really determined to find a way to make it work, even if that mean I have to monkey patch bundler.
Unfortunately that's not an option. We have hundreds of dev that may potentially run
Thanks, I'll try to hack around with this. But ultimately I think Bundler could behave differently here. If it wasn't for |
Yeah, I didn't really mean that as a serious suggestion, just wanted to point it out to show the currently brittleness of this.
Yeah, I really think the
I guess the answer of the question "why ruby is a platform" is... "legacy stuff", "historical decisions that most likely made total sense at the time", and those kind of answers. With all the recent changes though, "ruby" as a platform should be getting less and less used and be gradually removed from lock files, because it's not really necessary most of the times. |
So, it fix the problem I have, but has the very negative effect of forcing all our users to compile these huge gems from source when they could use the precompiled version.
Right, Most precompiled gems have But ultimately, what I really want to say is: "Include all the versions you need so that it is compatible with both 3.1.2 and 3.2.0.dev", so in a way I guess what I'm asking for is: # Gemfile
ruby "3.1.2", "3.2.0dev" Is this something you think would be doable? As said previously I know multi-ruby isn't something Bundler want to support, but I respectfully think it is a mistake because it prevent people like us from testing |
Ok, I think I may have found a dirty workaround:
|
Right, while before you would set
I personally didn't say I don't want to support something like that (or if I said that, I don't have such an opinion anymore). I just said it was never a goal and I'm not surprised it has issues. I think the problem with |
❤️ |
Stumbled up this issue as well, and wrote a spec of what I think the expected behavior should be in an ideal world: 3c29a15 context "when a gem has a source gem and a precompiled gem" do
context "when another platform-only gem is present" do
context "the Ruby version is not locked" do
it "does not remove the source gem nor RUBY platform from lockfile" do
build_repo2 do
# Source gem with no Ruby version requirement
build_gem("my-precompiled-gem", "3.0.0")
# Optional precompiled gem for the current platform, but wont work with
# future ruby versions
build_gem("my-precompiled-gem", "3.0.0") do |s|
s.platform = Bundler.local_platform # e.g. x86_64-linux
s.required_ruby_version = "< #{future_ruby_minor_version}"
end
# Platform-only
build_gem("no-ruby-platform-gem", "1.0.0") do |s|
s.platform = Bundler.local_platform # e.g. x86_64-linux
end
end
source = file_uri_for(gem_repo2)
# IMPORTANT: We cannot rule out the possibility that gems will be
# bundled on future ruby version.
gemfile <<~G
source "#{source}"
raise "This should not be loaded" unless RUBY_VERSION < "#{future_ruby_minor_version}"
gem "my-precompiled-gem"
gem "no-ruby-platform-gem"
G
bundle :install
# If the Ruby version is not locked, we shouldn't disqualify the
# source gem which will work on a more recent Ruby version.
expect(lockfile).to eq <<~L
GEM
remote: #{source}/
specs:
my-precompiled-gem (3.0.0)
my-precompiled-gem (3.0.0-#{Bundler.local_platform})
no-ruby-platform-gem (1.0.0-#{Bundler.local_platform})
PLATFORMS
ruby
#{Bundler.local_platform}
DEPENDENCIES
my-precompiled-gem
no-ruby-platform-gem
BUNDLED WITH
#{Bundler::VERSION}
L
end
end
end
end The key point being: Bundler shouldn’t remove the source gem because it’s feasible that Now, if the above example had specified I think the locking logic needs to take into account whether or not the user specified a |
This is a sledgehammer for a nail. We don’t want to force bundler to compile a gem when it doesnt need to. In many cases, we know that there are binaries for one Ruby version, but not another. It’s best to use the binary gem when possible and only fallback to compilation as an absolute last resort. The
I think this is the crux of the issue. Ideally, bundler could favor versions that have higher constraint specificity, but that seems bug-prone to implement and likely backwards incompatible. Another way would be to add an optional |
My naive idea to approach this, not sure how it will work in practice, is to handle |
What was the end-user or developer problem that led to this PR?
With #5495 we started being strict about lockfiles locked to "ruby" but not including exclusively gems NOT platform specific.
This was done because:
However, with this fix,
bundle update
orbundle outdated
can no longer be run on already existing lockfiles with the previous problem, generating a missing gems error like the following:What is your fix for the problem, implemented in this PR?
My fix is to automatically remove the "ruby" platform from these "corrupted" lockfiles, so that they resolve properly.
Fixes #5743.
Make sure the following tasks are checked