guard / listen

The Listen gem listens to file modifications and notifies you about the changes.
https://rubygems.org/gems/listen
MIT License
1.92k stars 246 forks source link

use ruby_dep for gemspec Ruby version constraint #377

Closed e2 closed 8 years ago

e2 commented 8 years ago

This allows limiting officially supported Ruby versions to a "sane" list extracted from the .travis.yml file.

coveralls commented 8 years ago

Coverage Status

Coverage decreased (-0.02%) to 97.679% when pulling eda4c307124793267676891f0b1065bb42e23929 on use_ruby_dep_gem into 6276301deec5f322ec5f7d9d61401605d26bf37f on master.

coveralls commented 8 years ago

Coverage Status

Coverage increased (+0.02%) to 97.728% when pulling ec47fe0e6abfd8cf80970dc8e02e117386670104 on use_ruby_dep_gem into 6276301deec5f322ec5f7d9d61401605d26bf37f on master.

nightscape commented 8 years ago

This PR breaks JRuby support. I'm guessing that JRuby presents itself as 2.2 and not >= 2.2.4 Is there a workaround?

rtyler commented 8 years ago

The JRuby 9.0.x series of releases claims RUBY_VERSION of in line with the 2.2 line of releases. Unfortunately the latest release, 9.0.5.0 is only parity with 2.2.3:

% irb
jruby-9.0.5.0 :001 > RUBY_VERSION
 => "2.2.3" 
jruby-9.0.5.0 :002 > 

@nightscape My work-around is to pin my transitive dependency to listen 3.1.1 :sob:

e2 commented 8 years ago

@nightscape , @rtyler - yes, that is an issue. Please do open a new issue for things like that.

see: https://github.com/guard/listen/issues/386

e2 commented 8 years ago

@nightscape, @rtyler - should be fixed in https://github.com/e2/ruby_dep/releases/tag/v1.2.0

Feel free to open issues for these, so you can track any "quick-releases" from there.

pmyjavec commented 8 years ago

This change seems to mean we can no longer have guard in our development dependencies if we want to test multiple versions of Ruby on TravisCI right?

All my travis builds suddenly fail since this went in:

https://travis-ci.org/pmyjavec/horatio/builds/127466668

e2 commented 8 years ago

@pmyjavec - running TravisCI builds on anything other than Ruby >= 2.2.5 doesn't make sense.

If you really want to (I can't think of a reason, honestly, no matter what your situation is), you can skip development dependencies on Bundler, e.g.: https://github.com/guard/listen/blob/master/.travis.yml#L2

A failing Travis build is a good thing. If it worked before, it doesn't mean it was a good thing.

pmyjavec commented 8 years ago

@e2,

I think you're being a little un-reasonable by taking that approach.

I did something similar to what you're suggested, not running Guard and my build works again. Happy times!

e2 commented 8 years ago

@pmyjavec,

I think you're being a little un-reasonable by taking that approach.

I find it the other way around. I haven't heard a single compelling reason to "avoid breaking builds".

Sure, "green builds" look nice, but actually people should be very happy when they fail for good reasons.

Broken builds are a good thing. And here, broken builds are broken, because those versions of Ruby are unsupported.

Even JRuby build is still currently broken on Listen. (And JRuby support was patched just yesterday - it likely never worked properly).

Reconsider how you feel about "builds working". If a build works and it shouldn't, that's a bad thing.

e2 commented 8 years ago

@pmyjavec - from that build log:

Gem::InstallError: ruby_dep requires Ruby version >= 2.2.3, ~> 2.2.

To me it's "works as expected". If you need to support older Rubies, let me know which version of Listen and which patches you need backported. And a compelling, real-life "business" reason why you can't drop running Travis builds using outdated Rubies ... or ... why you must upgrade Listen. (And not e.g. lock to an earlier version, as you should).

Running a Travis build with a "random" set of gem versions every time is going to break some day. SemVer doesn't protect you from that. And if you're not locking to specific versions, and you're just "upgrading" whatever the Travis builds "can upgrade" - then you're not worried about "backward compatibility", you just want "green builds" for the sake of "green builds".

e2 commented 8 years ago

@pmyjavec - just to close off - even if you could install ruby_dep, you'd have the same problem installing Listen. ruby_dep was originally code in Listen that was refactored out into a gem.

pmyjavec commented 8 years ago

No need to justify it, I'm talking about assuming that everyone has the luxury of running the latest stuff.

I pulled Guard out of my build and I'm happy with that approach, have a good day.

e2 commented 8 years ago

@pmyjavec -

No need to justify it, I'm talking about assuming that everyone has the luxury of running the latest stuff.

At the other extreme, most people will never upgrade Ruby until they have to. Ruby 2.2.4 isn't the "latest" by any stretch. The "latest" is Ruby head (in development). "Recommended" is Ruby 2.2 and 2.3.

There's a point where "latest" becomes "outdated". People can simply choose not to upgrade Listen. (Just like they choose not to upgrade Ruby). So they still have a choice.

have a good day.

Thanks! You too!

Antti commented 8 years ago

@pmyjavec @e2 I have the same issue. We have to use ruby 2.2.2 until our servers will be upgraded to a newer version, and that means guard is not usable anymore and have to be removed from our dependency list.

e2 commented 8 years ago

Check other issues. Lock to earlier Listen if you must, but Ruby < 2.2.4 has a serious vulnerability. On May 4, 2016 4:39 PM, "Andrii Dmytrenko" notifications@github.com wrote:

@pmyjavec https://github.com/pmyjavec @e2 https://github.com/e2 I have the same issue. We have to use ruby 2.2.2 until our servers will be upgraded to a newer version, and that means guard is not usable anymore and have to be removed from our dependency list.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/guard/listen/pull/377#issuecomment-216885806

Antti commented 8 years ago

But it doesn't depend on the any new features in ruby >= 2.2.3. If someone want's to do a security audit check, it's probably better to use some specific tool for that, rather than having a gem install failure for some unfounded reason. Anyway, we'll probably stay with the old listen gem or maybe reconsider us using guard.

e2 commented 8 years ago

Why exactly do you need support for Ruby < 2.2.3? I have never heard a single compelling use case, so I'm very open to being convinced.

How can you have more trouble upgrading to Ruby 2.2.3 than I'm going to have in supporting only secure and officially supported rubies?

Open an issue telling me exactly which version you expect to be supported with a compelling use case explaining why you must update Listen, but you're not allowed to upgrade Ruby. (A "broken Travis build" is not a use case - broken build is OK, broken tests are not). On May 5, 2016 11:12 AM, "Andrii Dmytrenko" notifications@github.com wrote:

But it doesn't depend on the any new features in ruby >= 2.2.3. If someone want's to do a security audit check, it's probably better to use some specific tool for that, rather than having a gem install failure for some unfounded reason. Anyway, we'll probably stay with the old listen gem or maybe reconsider us using guard.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/guard/listen/pull/377#issuecomment-217108340

pmyjavec commented 8 years ago

@e2,

In the official disclosure a work around is provided for people who can't upgrade Ruby; however, by your logic people, would not be able to deploy the provided fix because a third party has broken their CI pipeline (you). Also, you're only vulnerable if you'r using a specific library.

Secondly, if you're using the Ruby provided by a Linux distribution you have little control over the version of Ruby you're running, you could make your own packages but then you're also creating more overhead and potentially opening up other security holes.

Thirdly in some environments (PCI etc) you can't just change things at will, it can be against the law. I don't necessary like this but it's a fact of life for some.

Sorry but this is never going to fly in the real world, in theory I understand your approach but in practice it doesn't work well, you're going to have to change your approach or potentially lose users. I like Guard because it simplifies my development workflow; however, if all my build pipelines have to be complicated because of it, I will look for alternatives.

Regards

e2 commented 8 years ago

@pmyjavec - thanks for the reply.

a work around is provided for people who can't upgrade

Yes, but I have no way of reliably knowing if people are using the workaround or not. I just have to assume either everyone is vulnerable and they need to upgrade, or, they know what they're doing (like you) and the can just lock to what they need (which they should do anyway) and ask for backports (which I'd be happy to help with).

by your logic people, would not be able to deploy the provided fix because a third party has broken their CI pipeline (you)

For good reasons - otherwise people would unknowingly be deploying (and not just testing/CI) a vulnerable/incompatible/broken version. It's a provisioning failure (a good thing) not a production crash (a bad thing).

I know people are pissed off that their CI pipelines fail. Green is a lot "nicer" than red. But a green Travis build is not a metric of success. Because Travis doesn't show "bugs avoided" or "vulnerabilities avoided". If it did, it would be red, not green.

The build went from "green" to "red". So it looks like I "broke" something. In reality, it was broken already, because it started out "green" and not "red".

Broken install dependencies are better than failing tests, which are still better than failures in production. In quality control, the earlier things fail in the pipeline, the better.

(In web development, a JavaScript crash the client doesn't see is good for business).

Secondly, if you're using the Ruby provided by a Linux distribution you have little control over the version of Ruby you're running.

Yes, and if you're stuck with a vulnerable Ruby 2.2.2, and you're not allowed to do a PATCH-LEVEL upgrade to 2.2.4 ... isn't that already broken on the SemVer level? Ruby 2.2.4 doesn't introduce incompatibilities, and neither does Ruby 2.2.3. (Both 2.2.3 and 2.2.4 are SemVer compatible security patches).

So it's a double standard to say "I want to pessimistically lock to Listen" but also say "I want to lock to a specific patch-level and patch-number version of Ruby".

You can use the BrightBox PPA for Ubuntu: https://launchpad.net/~brightbox/+archive/ubuntu/ruby-ng.

If not, you can likely install using RVM or rbenv. If you need specific patches, you can just vendor Ruby with your app (much safer than any other option - and a good solution too, especially if you're committed to be "stuck" with an obsolete version of Ruby for a long time).

You could make your own packages but then you're also creating more overhead and potentially opening up other security holes.

Not having at least a PPA with a vulnerability fix is unlikely. In terms of "amount", there may be more security holes, but 2 CVEs reported on ruby-lang.org are a bigger threat than any "accidental" securities issues you could create that an attacker could know about. Someone that paranoid about being targeted specifically by criminal shouldn't be mindlessly upgrading versions of Listen to begin with. (Or relying on SemVer for upgrades at all).

The root issue here is exactly that: people relying on SemVer to avoid reading changelogs. To the point that they feel threatened when their Travis builds break.

That's fear as the result of FUD, which I'm trying to dispel here. The danger is being afraid of the wrong thing: "broken Travis build as a signal that upgrades may no longer be safe" (false security to begin with). Instead of being afraid of a real threat, like a well-known and exploitable CVE that script kiddies can start using today.

If a patch-level Ruby version is KNOWN to be vulnerable, then supporting that exact patch level doesn't make sense. (Supporting an earlier minor, such as Ruby 2.1 is a different subject).

Thirdly in some environments (PCI etc) you can't just change things at will, it can be against the law.

That's a law policy-maker problem if you're required by law to leave the back door of your app open to burglars. It's dumb laws vs insurance company policies you can opt-in/out of. The latter is much more reasonable. Solution: lobbying?

Again, if you have a strong case like that, open an issue so you can lock to a version of Listen, have your exact setup tested on Travis (unless you want to do that yourself), etc.

If you have a specific use case, I want to help you solve just that case, and nothing else. I'm just very selective about the backporting I do, because it's a tremendous expense. (Invisible to users).

Sorry but this is never going to fly in the real world, in theory I understand your approach but in practice it doesn't work well, you're going to have to change your approach or potentially lose users.

I'm more worried about losing contributors. I don't like Guard as it is now, and there's tons to fix. Adding an unjustified burden of "backward-compatibility" doesn't increase contributions nor users.

And that's because backward-compatibility kills features. (e.g. using Ruby 2.3.1 features becomes too expensive because they have to be reimplemented for Ruby 1.8.7 everywhere they're used, making them useless a benefit if you already have the 1.8.7 reimplementation, thus the codebase basically becomes Ruby 1.8.7).

Backward-compatibility isn't a "benefit-only" kind of change. Check out this: https://github.com/guard/listen/wiki/Support-for-older-versions-of-Ruby

I like Guard because it simplifies my development workflow; however, if all my build pipelines have to be complicated because of it, I will look for alternatives.

It depends how you use your pipeline. Your production code doesn't need to be run under the same version of Ruby as your development tools. E.g. Guard::RSpec runs RSpec in a process, so you can run it using RVM or rbenv in Ruby 1.8.7, while running Guard in 2.3.1 with 2.3.1 features used in your tools, etc. It's just one line in the Guardfile, so it's hardly complicated.

I'd rather implement more Guard features to make your pipeline easier to manage, than for spending time trying to avoid writing any new line of code in fear that it might break on some Ruby or some patch-level, and then be forced to backport that line on multiple, divergent branches of Listen, and make 8 releases of Listen for different major/minor versions, after running 30 hours worth of Travis builds to test that single line of code.

It doesn't matter how "simple" Ruby backward-compatibility in the Listen codebase is. You have a complex CI and so do I. To make it simpler, better features are needed (like Guard 3.x). I already need tons of time to make sure Guard 3.x will be a headache-free upgrade from Guard 2.x (given hundreds of plugins out there already). I don't have the resources to support every darn patch-number from Ruby 1.8.7-p0 to 2.3-head. That's about 2000 versions of Ruby if e.g. you assume Ruby itself doesn't follow SemVer.

I'm collecting issues to improve Guard before I start working on Guard 3.x. Listen needs an overhaul too, especially for ANY osx performance improvements. So if anything is complex or inconvenient, let me know.

Heck, if there's anything preventing you from being able to use Guard plugins on Ruby 2.3.1 while upgrading a codebase that has to be dual-tested on Ruby 1.8.7 and 2.3.1 (migration), I'd be happy to work on that instead. Even if you uncover a bug in RVM, I might be able to help you debug and work out a fix.

I also maintain Guard-RSpec, so if you need to conveniently run specs in an exact Ruby version matching your server (or multiple versions), I really would prefer to spend time there.

What I don't want to do is revert my changes, stop working on new features out of fear of backlash or more angry users and "lie" that any Listen is tested on anything other than Ruby >= 2.2.3 and "pretend" to be shocked when people get a crash using Listen in production environments (typically for tracking upload dirs).

e2 commented 8 years ago

One more distinction: Guard is "mostly" a development tool. And using outdated Rubies to use a development tool, makes little sense. Even 2.3.1 is a productivity boost. You optimize for productivity, and not backward compatibility.

Of course the production code should be tested in a production-like environment anyway. But production environment make poor development environments. It's "simpler" maybe to use two environments for both (that's why upgrading Ruby makes so much sense). But it doesn't make sense to strive to make "not upgrading" the simpler choice or the default.

RuboCop has a TargetRubyVersion option: https://github.com/bbatsov/rubocop#setting-the-target-ruby-version

This actually gives you a choice. "Backward-compatibility" doesn't. With backward compatibility, you're forced to write 1.8.7 code for the rest of your life, or people will get angry.

So I see 2 use cases for Listen: development and production (servers - e.g. watching download folders). On development you usually want the latest Ruby for productivity boosts and to keep the final codebase as up-to-date as possible (so you don't have to migrate in the near future or upgrade your project to a newer Ruby). On production servers, you don't want vulnerabilities.

2 different use cases, same outcome: upgrade Ruby.