mattbrictson / bundle_update_interactive

A stylish interactive mode for Bundler, inspired by `yarn upgrade-interactive`
MIT License
140 stars 3 forks source link

Ability to handle ignored groups #52

Open brandondrew opened 5 days ago

brandondrew commented 5 days ago

bundle update-interactive is a huge productivity boost, but I've found a case where it seems like it falls down (unless I'm missing something).

I have this in the Gemfile of an app I'm trying to upgrade,

group :oracle do
  gem "activerecord-oracle_enhanced-adapter", "~> 7.0"
  gem "ruby-oci8"
end

and I get the following error when I run bundle update-interactive:

Resolving latest gem versions...
Could not find gem 'activerecord-oracle_enhanced-adapter', because it's in the group 'oracle', configured to be ignored.
/Users/brandon/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/bundle_update_interactive-0.8.1/lib/bundle_update_interactive/bundler_commands.rb:32:in `parse_outdated': bundle outdated command failed (RuntimeError)
        from /Users/brandon/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/bundle_update_interactive-0.8.1/lib/bundle_update_interactive/updater.rb:55:in `find_withheld_gems'
        from /Users/brandon/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/bundle_update_interactive-0.8.1/lib/bundle_update_interactive/updater.rb:13:in `generate_report'
        from /Users/brandon/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/bundle_update_interactive-0.8.1/lib/bundle_update_interactive/cli.rb:60:in `generate_report'
        from /Users/brandon/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/bundle_update_interactive-0.8.1/lib/bundle_update_interactive/cli.rb:9:in `run'
        from /Users/brandon/.rbenv/versions/3.3.5/lib/ruby/gems/3.3.0/gems/bundle_update_interactive-0.8.1/exe/bundler-update-interactive:6:in `<top (required)>'
        from /Users/brandon/.rbenv/versions/3.3.5/bin/bundler-update-interactive:25:in `load'
        from /Users/brandon/.rbenv/versions/3.3.5/bin/bundler-update-interactive:25:in `<main>'
mattbrictson commented 5 days ago

Thanks for the report! This is definitely a bug. update-interactive currently does not know how to handle ignored groups.

The problem stems from how update-interactive identifies "held-back" gems. It first looks for all gems in the Gemfile that have a version specifier, like the ~> 7.0 in your example. Then it passes those gems to bundle outdated.

It seems that if you pass a gem to bundle outdated that is in an ignored group, Bundler fails, as we are seeing in the error message.

To fix this, somehow update-interactive needs to be aware of groups that are ignored, and exclude those gems from the outdated check.

I'm tagging this issue as help wanted because I could use some suggestions on how best to do this.

mattbrictson commented 5 days ago

A quick fix would be to call bundle outdated with no explicit gem arguments; this would check all gems, implicitly skipping ignored groups. The problem is that checking all gems is potentially a lot slower than checking the few specific gems that we care about (i.e. the ones with explicit version constraints). So it would work more reliably, but be slower.

mattbrictson commented 5 days ago

@brandondrew what's the expected behavior in the situation where the :oracle group is ignored? Do you expect update-interactive to still show you whether gems in that group are outdated? Or should it completely ignore them?

brandondrew commented 5 days ago

@brandondrew what's the expected behavior in the situation where the :oracle group is ignored? Do you expect update-interactive to still show you whether gems in that group are outdated? Or should it completely ignore them?

It should take that group into consideration because (as I discovered by doing things the old-fashioned way, without bundle_update_interactive), the Oracle drivers are old and don't support upgrading Rails. So I don't want to upgrade Rails to a point that it works locally (where I have the database in SQLite) and then chokes on the server (where it's using Oracle).

brandondrew commented 5 days ago

A quick fix would be to call bundle outdated with no explicit gem arguments; this would check all gems, implicitly skipping ignored groups. The problem is that checking all gems is potentially a lot slower than checking the few specific gems that we care about (i.e. the ones with explicit version constraints). So it would work more reliably, but be slower.

This might be a terrible idea since (1) I haven't read the code for this gem, and (2) don't have a deep understanding of how Bundler does its magic, and (3) might not have completely understood your description of the problem... but would it make sense to do things the faster way by default but then in a rescue block fall back to a more reliable approach? If we assume that 99+% of the time the faster way is sufficient, we can kind of have our cake (speed) and eat it too (have it be reliable).

brandondrew commented 5 days ago

@brandondrew what's the expected behavior in the situation where the :oracle group is ignored? Do you expect update-interactive to still show you whether gems in that group are outdated? Or should it completely ignore them?

IF I'm not mistaken, I think the :oracle group is only ignored for purposes of locally installing gems, but all determinations of which gems are compatible need to take those gems into account.

(This is an app that I virtually never work on, and didn't originally set up.)

mattbrictson commented 4 days ago

would it make sense to do things the faster way by default but then in a rescue block fall back to a more reliable approach?

It is a little messy, but yes, I think this might be the easiest approach.

Full disclosure: I am not planning on fixing this bug at the moment, but I will accept a PR. I may circle back and open a PR at a later date when I have more availability.