[Rubygems-developers] What is right and wrong with dependencies definitions?

Eric Hodel drbrain at segment7.net
Fri Nov 9 20:33:08 EST 2007

On Nov 9, 2007, at 16:08 , Chad Woolley wrote:
> On 11/9/07, Eric Hodel <drbrain at segment7.net> wrote:
>>> What is the best approach for this? Include everything as  
>>> dependency?
>> Including everything is the best approach.
>> Things that need to be discussed are:
>> * should developer dependencies by installed by default?
>> * what does the command-line option look like?
>> * what happens on uninstall?
>> * what should `gem check` do if all dependencies aren't installed?
>> Its really easy to say "gems should have developer dependencies".
>> Its a lot of work to make it a reality.
>> [1] http://www.bikeshed.org/
>> [2] http://rubyforge.org/tracker/index.php?
>> func=detail&aid=13287&group_id=126&atid=578
> Hi,
> <disclaimer>I'm really trying to NOT bikeshed, and know I won't have
> the time to do anything about it other than pimp my tool I wrote to
> address this issue.</disclaimer>

Granted.  In the general community (ruby-talk) there is much  
bikeshedding about this feature request and no action.  You're  
probably the person most-likely to have a valid opinion about how the  
feature should behave.

> I agree that this will probably be really hard to implement in
> rubygems, and I'll believe you that it's not worth it.  However,
> there's still valid reasons for both sides of the argument.

I'm not saying its not worth doing, but it's much, much easier said  
than done.

> On one hand, it can be considered dangerous to include unused
> dependencies on a production box.  Here's a real case in point that
> just happened to us on a shared box.  There's a bug in the latest edge
> rails gem that the mere existence of an unused soap4r dependency
> causes failures: http://dev.rubyonrails.org/ticket/10001  Now, we were
> able to handle this by auto-installing and locking down the soap4r
> version (using GemInstaller), and we were proactive enough to find it
> on a demo box instead of prod, but it's still an example of a
> completely unrelated dependency causing problems.

Granted, but I think that's orthogonal to this feature.  (Especially  
since you're using a development version of something in production.)

> Also, in some cases, it just obviously doesn't make sense to include
> all dependencies.  For example, on GemInstaller, it is a tool itself
> to manage dependencies, and I don't want to force everyone who uses it
> to install the dozen-plus build- and deploy- and test-time
> dependencies I have
> (http://geminstaller.rubyforge.org/svn/trunk/geminstaller.yml).  This
> would freak some people out when they installed it and make them not
> want to use the gem.

I've installed things that easily have more dependencies than that.   
I think lots of dependencies with a small gem is a good thing, since  
it means the author is probably being a good citizen.

I've heard an alternate version of this argument, "I audit  
everything, and this is too much", but there's just too much code out  
there for me believe any effective auditing is performed.  (For  
example, recent vulnerabilities in pcre and perl with respect to  
regular expressions.)

> Plus, it's very likely (especially in the case
> of Rspec) that one of my dependency versions conflicts with something
> else on their system, and unless they have their rspec version locked
> down everywhere (unlikely) the mere installation of my gem will screw
> them if it auto-installs a newer version of rspec that's incompatible
> with their old specs.

I believe that RubyGems has the ability to handle this gracefully  
with sane versioning schemes combined with the existing requirement  
specifiers (including '~>'), and that this is primarily a gem author  
education problem.  When severity of changes doesn't match changes in  
version numbers, everybody is going to suffer.

> Now, playing advocate for the other side, it may be a GOOD thing to
> always include all dependencies on all platforms.  By NOT doing so,
> you may open yourself up to unexpected behavior on non-development
> platforms.  This could happen if the absence of a 'development'
> dependency somehow breaks your application through the dynamic magic
> of Ruby.  This is very possible, and I think I just convinced myself
> that I agree with you, at least in the case of Rails apps (because
> this is what we've done for dozens of projects and it works fine).

FreeBSD's ports has run and build dependencies.  I think its fine for  
RubyGems to have an equivalent.  Retrofitting the distinction on is  
complicated, though.

> Regardless, there are valid points on both sides.  If building this
> support into RubyGems really is too hard (and I believe you), then we
> need alternate approaches.

Again, I don't think it's too hard, but it is harder than people  
think.  Or, it's easy, once we know exactly what it is supposed to do  
(which is hard).

> Ok, pimp-mode on: I think that my GemInstaller tool
> (http://geminstaller.rubyforge.org) is perfect for this - it centrally
> manaages all your dependencies via an erb-parsed file (or files).
> This allows you to explicitly manage your dependencies, and have them
> behave differently based on whatever criteria you want - RAILS_ENV,
> hostname, environment variables, whatever.  If you have a startup
> check in your app that installs and loads the appropriate gems in
> development or test mode (rake or test_helper), then you can only
> include actual runtime dependencies in your gem, but ensure that
> anyone who wants to build/test your app still has the gems they need.

For production Rails apps, I tend manually lock down versions  
explicitly.  `gem lock` is a lightweight way to generate the #gem  
calls for this (which I discovered recently), but doesn't handle all  
the other issues that your tool does.

Poor workers blame their tools. Good workers build better tools. The
best workers get their tools to do the work for them. -- Syndicate Wars

More information about the Rubygems-developers mailing list