Foreman: Update thor dependency

Created on 4 Jun 2019  ·  15Comments  ·  Source: ddollar/foreman

foreman depends on an old version of thor that is incompatible with up-to-date gems like Rails 6. The prevailing advice seems to be to leave out foreman from Gemfile, but this seems like a workaround. (We had a project for years with foreman in the Gemfile, no problems.)

In any event, why does foreman.gemspec reference a version of thor from 2014? Why not upgrade it?

See also #452, #653, (and #688, #725, etc.), as well as affecting other projects, e.g. https://github.com/bkeepers/dotenv/issues/324

Most helpful comment

@ddollar I disagree with https://github.com/ddollar/foreman/wiki/Don't-Bundle-Foreman.

Foreman at @cultureamp is a developer tool, much like rubocop, rspec-rails, cucumber, factory_bot, etc. It is _convenient_ to have this specified in the Gemfile, as it will then be available for us to use immediately, just like those other tools are.

I would specify it like this:

group :development do
  gem 'foreman', require: false
end

By adding it to the development group it would mean it is not available on production, and is not a vulnerability vector.


So with that in mind, it would mean that the Gemfile.lock receives these dependencies:

foreman (0.85.0)
  thor (~> 0.19.1)

This causes conflicts with the new railties 6.0 gem, as it has a dependency on thor of >= 0.20.3, < 2.0.

I strongly believe that foreman _should_ be placed in an application's Gemfile because _it is a developer tool_ and I equally strongly believe foreman's thor dependency should be updated, or at least relaxed.

All 15 comments

Is this even still being maintained?

@alaxalves we just switched to forego, seems to be a drop-in replacement.

@alaxalves we just switched to forego, seems to be a drop-in replacement.

@mfilej This is great, but how do we keep using Foreman in a Rails app?

@alaxalves What exactly do you mean by "using in a rails app"? Are you using for something other than running processes? For us it was just a matter of installing forego on our development machines and servers (docker images) and changing the command from foreman start to forego start.

@alaxalves What exactly do you mean by "using in a rails app"? Are you using for something other than running processes? For us it was just a matter of installing forego on our development machines and servers (docker images) and changing the command from foreman start to forego start.

I meant using it as a gem.

@alaxalves sorry, I don't know what that means. In our case we just dropped the foreman gem from our gemfiles. Does anything in your code rely on the foreman gem?

@alaxalves sorry, I don't know what that means. In our case we just dropped the foreman gem from our gemfiles. Does anything in your code rely on the foreman gem?

Yes, I've been using it. But I'll start using forego. I just didn't want to install it as a pkg or something like it. I'd like to keep using as a dependency defined in my Gemfile. Anyway, thanks for your time :smile:

I'm seeing this exact same issue when performing an upgrade to Rails 6.0.0, which depends on a more recent version of thor. Bundler is resolving it by downgrading foreman, dotenv and thor. I've tried forcing the latest version of foreman in the Gemfile and this shows the dependency issue:

Bundler could not find compatible versions for gem "thor":
  In snapshot (Gemfile.lock):
    thor (= 0.20.3)

  In Gemfile:
    foreman (~> 0.85.0) was resolved to 0.85.0, which depends on
      thor (~> 0.19.1)

    rspec-rails was resolved to 3.8.2, which depends on
      railties (>= 3.0) was resolved to 6.0.0, which depends on
        thor (>= 0.20.3, < 2.0)

Running bundle update doesn't resolve the issue either.

As far as I'm aware Forego isn't written in Ruby so that's not a great workaround as it will add another dependency to the project.

I highly suggest that you do not include foreman in your Gemfile. I've written up my reasoning here:

https://github.com/ddollar/foreman/wiki/Don't-Bundle-Foreman

Great. I had a look at your writeup and it makes perfect sense. Thanks for clarifying that... and thanks for putting foreman out there!

I highly suggest that you do not include foreman in your Gemfile. I've written up my reasoning here:

https://github.com/ddollar/foreman/wiki/Don't-Bundle-Foreman

Why not using gem 'foreman', require: false instead of not including it ?
That's what i use for lots of dev tools (like linters, etc...), even some gems documentation seems to be ok with require: false (cf: https://github.com/rubocop-hq/rubocop#installation, https://github.com/sds/haml-lint#installation)

@ddollar I disagree with https://github.com/ddollar/foreman/wiki/Don't-Bundle-Foreman.

Foreman at @cultureamp is a developer tool, much like rubocop, rspec-rails, cucumber, factory_bot, etc. It is _convenient_ to have this specified in the Gemfile, as it will then be available for us to use immediately, just like those other tools are.

I would specify it like this:

group :development do
  gem 'foreman', require: false
end

By adding it to the development group it would mean it is not available on production, and is not a vulnerability vector.


So with that in mind, it would mean that the Gemfile.lock receives these dependencies:

foreman (0.85.0)
  thor (~> 0.19.1)

This causes conflicts with the new railties 6.0 gem, as it has a dependency on thor of >= 0.20.3, < 2.0.

I strongly believe that foreman _should_ be placed in an application's Gemfile because _it is a developer tool_ and I equally strongly believe foreman's thor dependency should be updated, or at least relaxed.

Even if Foreman should not be put in Gemfiles, what is the point of keeping it stubbornly dependent on a long outdated version of Thor?

Any change can introduce bugs so I would turn this question around. In the absence of a security vulnerability or desired new feature what is the advantage of upgrading a dependency that could introduce breaking changes?

  1. Older libraries are harder to upgrade. The longer you wait, the more difficult it will be when you actually have to/decide to upgrade. (If it won't be harder in the future, that's because the library does not have many incompatible changes, so it wouldn't be hard now either.) It makes sense not to waste time on overly frequent upgrade cycles, but six years is a long time.

  2. Security vulnerabilities in random older versions of software are less likely to be publicly discovered, because people aren't using them or looking into them, but the vulnerabilities would exist nevertheless. (Caveats for ancient mainframes, etc. but this is Internet-connected Github software.) Of course, security vulnerabilities in thor are undoubtedly low priority, because it is a local command-line tool, especially in the foreman use case. But this means under your policy, thor is unlikely to be upgraded, ever. (A security vulnerability was reported in thor, but it was closed because "Thor is a system tool that unlikely will receive user input", https://github.com/erikhuda/thor/issues/514).

  3. Incompatible with other libraries, the issue at-hand here. There is a workaround, but putting foreman in the Gemfile is clearly a common and useful use case. There are apparently even other gems that depend on foreman and thus must put it in their Gemfile. (This could potentially also affect test quality, if users have a mixed up-to-date system while the test environment has a bare install with old versions, though may not be likely in the foreman/thor case.)

In conclusion, from a technical perspective it seems like a close call, but from a systems and ecosystem perspective it's essential, and becomes moreso as the years drift by (and I'm not someone who thinks "newer means better"). You may think no one will use your software by the time the thor dependency is a full ten years old, but you also get collateral effects where people decide to stop using foreman because it is incompatible or appears unmaintained.

(Also, there is the distinct possibility that upgrading the dependency will take five minutes and cause zero bugs.)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rtyler picture rtyler  ·  8Comments

abrambailey picture abrambailey  ·  3Comments

maxehmookau picture maxehmookau  ·  5Comments

kurtnovack picture kurtnovack  ·  5Comments

MathieuGilbert picture MathieuGilbert  ·  18Comments