Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

does not install latest version of gems dependencies, installs older instead #3089

Closed
jrochkind opened this issue Jul 9, 2014 · 17 comments
Closed

Comments

@jrochkind
Copy link
Contributor

bundler 1.6.3

I have isolated to this reproduction Gemfile:

source "https://rubygems.org"

gem "rails", ">= 3.2.12", "< 4.1"
gem "sass-rails"

I would expect that to install the latest Rails < 4.1 available: 4.0.8

Instead it installs rails 4.0.5. Gemfile.lock

That would make sense only if there were for some reason no sass-rails compatible with 4.0.8, if the latest rails a sass-rails could work with were rails 4.0.5.

But that doesn't seem to be the case, and it installed sass-rails 4.0.1 -- which isn't the latest sass-rails either, but is still apparently compatible with rails 4.0.8.

So why did it choose to install an older rails and an older sass-rails?

If we choose to force the issue for testing purposes:

source "https://rubygems.org"

gem "rails", ">= 3.2.12", "< 4.1", "= 4.0.8"
gem "sass-rails"

Then it is perfectly happy to install Rails 4.0.8 -- this time with sass-rails 4.0.3, the most recent sass-rails too. Gemfile.lock

In the first case, rails 4.0.8 and sass-rails 4.0.3 would still seem to be the most recent gems that satisfy the dependencies expressed. Why is bundler installing older versions instead? Is this a bug?

@indirect
Copy link
Member

indirect commented Jul 9, 2014

If you actually care about the versions that you get, you must specify them in the Gemfile. You are explicitly saying that you will accept any version of Rails equal to or above 3.2.12, and that is exactly what you are getting. If that's not okay, change your requirement.

Bundler generally tries to use the newest versions. It is literally impossible to guarantee that you will always get the newest possible version without exhaustively checking every possible combination of versions, which could potentially take as long as infinity time. We avoid that, but a side effect is sometimes picking versions that are lower than versions that would be acceptable.

You can see the precise order of versions that Bundler tried by running DEBUG_RESOLVER=true bundle install.

@indirect indirect closed this as completed Jul 9, 2014
@jrochkind
Copy link
Contributor Author

Okay, thanks.

I think that contradicts many people's mental model of bundler. Which is: If without changing my Gemfile, I run bundle update, and there's been a new version of a gem released that satisfies my dependencies -- I'll get it.

I think you're saying... not neccesarily. Since what you say applies to bundle update as well as bundle install (verified via testing), then running bundle update without touching your Gemfile may not get you an update that is available.

I understand that my (and I think others?) mental models of what's going on is not feasible to implement. But I wonder if it requires documentation or other education to help developers understand what bundler is setting out to do.

I think I'm not alone in having through bundler promissed to always get the latest gems that satisfied dependency requirements -- or that running bundle update would always get you the latest available version(s) that satisfied expressed dependencies.

(Interestingly, using an older version of bundler I happened to have on hand, it did succesfully install latest versions of gems in my first example. But I understand there may be other cases where it too would not have).

@indirect
Copy link
Member

indirect commented Jul 9, 2014

The Bundler resolver is definitely a work in progress, and we adjust the tradeoffs between specific versions and resolving quickly based on user feedback.

Bundler has consistently not provided the newest possible version of every gem for the entirety of its existence, and it does result in a lot of tickets being opened. In most cases, it turns out to be the result of Bundler having to pick between the newest version of one gem or a different gem, and Bundler picks the gem the user doesn’t care about having the newest version of. That’s why it’s so important to make your Gemfile version requirements accurately reflect your actual requirements.

I recognize that your assumption that Bundler would give you the newest possible version seemed valid at the time, but the docs only say that you will get a version that meets your requirements, not the latest. Is there anywhere we could expand the docs to make it clearer that the newest versions of everything simply isn’t feasible?

Somewhat related to this, there is also the possibility that this particular case is actually a regression in the resolver that can be fixed without adding infinite time. :) @Who828, any ideas about how we could do that?

On Jul 9, 2014, at 2:50 PM, Jonathan Rochkind notifications@github.com wrote:

Okay, thanks.

I think that contradicts many people's mental model of bundler. Which is: If without changing my Gemfile, I run bundle update, and there's been a new version of a gem released that satisfies my dependencies -- I'll get it.

I think you're saying... not neccesarily. Since what you say applies to bundle update as well as bundle install (verified via testing), then running bundle update without touching your Gemfile may not get you an update that is available.

I understand that my (and I think others?) mental models of what's going on is not feasible to implement. But I wonder if it requires documentation or other education to help developers understand what bundler is setting out to do.

I think I'm not alone in having through bundler promissed to always get the latest gems that satisfied dependency requirements -- or that running bundle update would always get you the latest available version(s) that satisfied expressed dependencies.

(Interestingly, using an older version of bundler I happened to have on hand, it did succesfully install latest versions of gems in my first example. But I understand there may be other cases where it too would not have).


Reply to this email directly or view it on GitHub.

@jrochkind
Copy link
Contributor Author

Woah, and another of my assumptions about bundler is also felled here.

I had assumed that running bundle update was always a strict superset of running bundle update some_gem.

But in the first example, it's not. If I run bundle install to get the Gemfile.lock in the first example, and then run bundle update (no arg) -- there is no change to the Gemfile.lock. Which isn't too surprising.

However, if I run bundle update rails, it succesfully updates rails from 4.0.5 to 4.0.8.

Mind blown. I didn't realize bundle update {specific gem} could possibly get that gem to a higher version than bundle update (everything) would.

This definitely makes the use of bundler a lot trickier, things don't work as consistently as we thought. Consider semver too -- I thought the promise of semver+bundler was, if your dependencies succesfully follow semver, and express your dependency requirements in terms of semver, then you can run bundle update without editing your Gemfile at any time and without manually researching releases to: 1) Get more recently released versions of any of your dependecies that 2) will not cause any backwards incompat problems, because they followed semver.

It turns out you can't count on 1. bundle update may not get more recently released gems. But bundle update that_gem_name might get recently released gems bundle update didn't.

I'm honestly not sure where to document this or how. I'm feeling pretty mind-blown, it violates what I thought were the basic operating principles of bundler. But I have the distinct impression that it was the original intention for bundler to work this way, that's later proven infeasible. I almost feel like it requires an announcement or something, that it was discovered to be infeasible. It seems kinda huge to me.

Note that this applies to dependencies expressed in gemspecs as resolved by bundler too, of course -- I just reproduced in a Gemfile for an isolation case.

To be fair, I think bundler mostly works as expected. If there were some way to document in exactly what cases bundler fails to work that way, that might be useful, so people could try to avoid them. I'm not sure if that's feasible.

@indirect
Copy link
Member

indirect commented Jul 9, 2014

When you update a single gem, only that gem and its dependencies are allowed to be updated. That means that the resolver is freed to try a much smaller problem space, and apparently means that it is able to find the newest version of Rails.

There was never an explicit goal of installing the newest versions of every gem. The goal has always been to install versions of gems that meet the requirements in the Gemfile and all work together. Newest possible versions is a nice-to-have that we aim for when we can.

I’m very confused about what part of Bundler usage is trickier—Bundler is still giving you a version that meets the range you request, like it always has. The basic operating principle of Bundler is: 1) the same version of every gem that you list 2) on every machine running your application.

Can you point to the places in the docs that gave you the impression Bundler would give you the newest possible versions? It seems like we can at least start there.

On Jul 9, 2014, at 3:05 PM, Jonathan Rochkind notifications@github.com wrote:

Woah, and another of my assumptions about bundler is also felled here.

I had assumed that running bundle update was always a strict superset of running bundle update some_gem.

But in the first example, it's not. If I run bundle install to get the Gemfile.lock in the first example, and then run bundle update (no arg) -- there is no change to the Gemfile.lock. Which isn't too surprising.

However, if I run bundle update rails, it succesfully updates rails from 4.0.5 to 4.0.8.

Mind blown. I didn't realize bundle update {specific gem} could possibly get that gem to a higher version than bundle update (everything) would.

This definitely makes the use of bundler a lot trickier, things don't work as consistently as we thought. Consider semver too -- I thought the promise of semver+bundler was, if your dependencies succesfully follow semver, and express your dependency requirements in terms of semver, then you can run bundle update without editing your Gemfile at any time and without manually researching releases to: 1) Get more recently released versions of any of your dependecies that 2) will not cause any backwards incompat problems, because they followed semver.

It turns out you can't count on 1. bundle update may not get more recently released gems. But bundle update that_gem_name might get recently released gems bundle update didn't.

I'm honestly not sure where to document this or how. I'm feeling pretty mind-blown, it violates what I thought were the basic operating principles of bundler. But I have the distinct impression that it was the original intention for bundler to work this way, that's later proven infeasible. I almost feel like it requires an announcement or something, that it was discovered to be infeasible. It seems kinda huge to me.

Note that this applies to dependencies expressed in gemspecs as resolved by bundler too, of course -- I just reproduced in a Gemfile for an isolation case.

To be fair, I think bundler mostly works as expected. If there were some way to document in exactly what cases bundler fails to work that way, that might be useful, so people could try to avoid them. I'm not sure if that's feasible.


Reply to this email directly or view it on GitHub.

@jrochkind
Copy link
Contributor Author

One example, specifically about bundle update:

This command will update rack-cache and its dependencies to the latest version allowed by the Gemfile (in this case, the latest version available).

.

If you want to update every gem in the Gemfile to the latest possible versions, run: $ bundle update

http://bundler.io/v1.6/rationale.html

@jrochkind
Copy link
Contributor Author

Also, not from official bundler documentation, but from a post by yehuda katz, where a lot of people learned about bundler:

because you may want to run bundle update at some point in the future, which will update everything to the latest possible versions, you might want to use version specifiers in your Gemfile that seem likely to work into the future.

http://yehudakatz.com/2010/08/21/using-considered-harmful-or-whats-wrong-with/

@jrochkind
Copy link
Contributor Author

For what it's worth, if anyone's curious, this particular example succesfully installs latest version of Rails and sass_rails with bundler 1.5.3, but stops doing so with bundler 1.6.0.

I understand there are likely be some other examples that failed to install latest versions of all gems in all previous versions of bundler (not neccesarily the same examples in each version). It's not too important to me that this particular example be 'fixed' (or 'improved' if it's not considered a bug), I can work around it. I remain somewhat disturbed that bundler doesn't behave like I thought, and do think it would be good if the 'unexpected' cases could be minimized, if not eliminated.

@indirect
Copy link
Member

We aim to minimize them, and we're working on this particular example, both adding a test and fixing it as a regression.

In general, we want to minimize this stuff. That said, "resolving to some version that was requested in a reasonable amount of time" always has to win over "resolve to a particular version" when they conflict.

On Thu, Jul 10, 2014 at 7:12 AM, Jonathan Rochkind
notifications@github.com wrote:

For what it's worth, if anyone's curious, this particular example succesfully installs latest version of Rails and sass_rails in bundler 1.5.3, but stops doing so in bundler 1.6.0.

I understand there are likely be other examples that failed to install latest versions of all gems in all previous versions of bundler. It's not too important to me that this particular example be 'fixed' (or 'improved' if it's not considered a bug), I can work around it. I remain somewhat disturbed that bundler doesn't behave like I thought, and do think it would be good if the 'unexpected' cases could be minimized, if not eliminated.

Reply to this email directly or view it on GitHub:
#3089 (comment)

@jrochkind
Copy link
Contributor Author

Cool, thanks.

I would not have filed this issue if I had known that bundler did not in fact promise to update to latest gems meeting dependencies. But apparently it's good I did, because you did consider it a bug/problem, because it's a regression? In what cases do you want people filing issues for this? Is there a policy to make sure future releases of bundler don't fail to find latest version in any cases where past versions succeeded?

@indirect
Copy link
Member

We add tests to prevent regressions, and we just didn't have a test for cases like this. In general, it's okay to open a ticket about things that you don't understand based on the existing documentation, so thanks for reporting this!

On Thu, Jul 10, 2014 at 1:12 PM, Jonathan Rochkind
notifications@github.com wrote:

Cool, thanks.

I would not have filed this issue if I had known that bundler did not in fact promise to update to latest gems meeting dependencies. But apparently it's good I did, because you did consider it a bug/problem, because it's a regression? In what cases do you want people filing issues for this? Is there a policy to make sure future releases of bundler don't fail to find latest version in any cases where past versions succeeded?

Reply to this email directly or view it on GitHub:
#3089 (comment)

@jcoyne
Copy link

jcoyne commented Sep 3, 2014

👍 This is definitely a regression that ought to be fixed. When you didn't have a version listed in the Gemfile, bundle update mygem used to get the most recent version that matched the rest of the restrictions in the Gemfile. It's recently stopped doing that.

@n-studio
Copy link

n-studio commented Nov 1, 2014

bundle update mygem is definitely useless right now since a bundle update will cancel its effect and revert to an older version.

edit:
Would it be a good idea to print a warning if the selected version is not the last available? For instance:
gem 'rails', '~> 4.0.0'
bundle update
Using rails 4.0.10 (was 4.0.11)
Warning: rails 4.0.11 is available. Please update your Gemfile

Who828 added a commit that referenced this issue Nov 24, 2014
Currently Bundler is aggressive to try different
versions of exsiting gem parents before
exhausting different versions of parents of
current conflicting gem.

By making sure we travase the current conflicting
dependency tree before trying to make use of exsiting
(activated) gem dependency tree, we reduce the number of
conflicts and activation of gems older then the latest
compitable version.

However, a long term solution would be to make the resolver smarter
by making it understand if current requirement conflict is caused by
either by it's parent or existing gem parent by looking at each of their
dependency requirements.
@Who828
Copy link
Contributor

Who828 commented Nov 24, 2014

I have fixed this issue (hopefully) in this branch, https://github.com/bundler/bundler/tree/resolver_bug_fix

Can you please try it once to ensure things are fixed at your end?

Meanwhile I will do some regression testing before we push out a pre release version.

@TimMoore
Copy link
Contributor

Fixed in v1.7.9.

@faustoct1
Copy link

is that fixed? still getting older versions after gem update

@AlexWayfer
Copy link

AlexWayfer commented Jul 10, 2018

It doesn't look fixed:

> env DEBUG_RESOLVER=true bundle update r18n-core

...

Creating possibility state for r18n-core (~> 3.0) (1 remaining)
  Attempting to activate [r18n-core (3.0.0), r18n-core (3.0.1), r18n-core (3.0.2), r18n-core (3.0.3), r18n-core (3.0.4)]
  Found existing spec ([r18n-core (3.0.3)])
  Creating possibility state for r18n-core (1 remaining)
    Attempting to activate [r18n-core (0.1), r18n-core (0.1.1), r18n-core (0.2), r18n-core (0.2.1), r18n-core (0.2.2), r18n-core (0.2.3), r18n-core (0.3), r18n-core (0.3.1), r18n-core (0.3.2), r18n-core (0.4), r18n-core (0.4.1), r18n-core (0.4.2), r18n-core (0.4.3), r18n-core (0.4.4), r18n-core (0.4.5), r18n-core (0.4.6), r18n-core (0.4.7), r18n-core (0.4.7.1), r18n-core (0.4.8), r18n-core (0.4.9), r18n-core (0.4.10), r18n-core (0.4.11), r18n-core (0.4.12), r18n-core (0.4.13), r18n-core (0.4.14), r18n-core (1.0.0), r18n-core (1.0.1), r18n-core (1.1.0), r18n-core (1.1.1), r18n-core (1.1.2), r18n-core (1.1.3), r18n-core (1.1.4), r18n-core (1.1.5), r18n-core (1.1.6), r18n-core (1.1.7), r18n-core (1.1.8), r18n-core (1.1.9), r18n-core (1.1.10), r18n-core (1.1.11), r18n-core (2.0.0), r18n-core (2.0.1), r18n-core (2.0.2), r18n-core (2.0.3), r18n-core (2.0.4), r18n-core (2.1.0), r18n-core (2.1.1), r18n-core (2.1.2), r18n-core (2.1.3), r18n-core (2.1.4), r18n-core (2.1.5), r18n-core (2.1.6), r18n-core (2.1.7), r18n-core (2.1.8), r18n-core (2.2.0), r18n-core (3.0.0), r18n-core (3.0.1), r18n-core (3.0.2), r18n-core (3.0.3), r18n-core (3.0.4)]
    Found existing spec ([r18n-core (3.0.3)])

...

Bundler attempted to update r18n-core but its version stayed the same

Why?! What is existing spec?

Bundler version 1.16.1


OK, sorry: r18n-rails-api 3.0.3 had r18n-core = 3.0.3 dependency.

Need to update both:

bundle update r18n-core r18n-rails-api

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants