Closed e2 closed 8 years ago
Just show a warning to avoid further SemVer discussions.
Well, I was unpleasantly surprised that builds on Travis started failing when it pulled in listen 3.1 just now. So I'd argue that I don't care about runtime warnings, but just want my builds not to fail suddenly :disappointed:.
@mvz - a failing build is a good thing. It's something to look forward to. It's a problem discovered during development and not production.
It's all about the mindset.
Sure, failing builds don't seem nice - we prefer green rather than red. But what use is a green build and yet a crash in production?
A failing build is a warning that something is wrong. The error here isn't in Listen, but in assumptions about Listen which were incorrect.
@e2, to give a little more background, I'm talking about builds for https://github.com/publify/publify, which does not use listen at all in production, but uses listen as part of guard, which one of its developers uses while developing.
It's a problem discovered during development and not production.
True, I was able to remove listen from the bundle now to ensure our users can still use Publify on MRI 2.1.
The error here isn't in Listen, but in assumptions about Listen which were incorrect.
I agree, but why not revert to supporting more Rubies?
@mvz -
I'm talking about builds for https://github.com/publify/publify
For builds on e.g. Travis, you probably want to run bundle install --without=development
. Though, you have to make sure all dependencies for test group are satisfied. You can check out the Gemfile
, .travis.yml
, Rakefile
and listen.gemspec
which are adapted for this. For the same reason, you don't want e.g. 'spring' neither installed nor used on Travis.
I agree, but why not revert to supporting more Rubies?
Plenty of reasons. The biggest one is: security reasons. If Ruby core devs aren't supporting Ruby 2.1 anymore, why should anyone else? If you give people eternity to not upgrade their broken and vulnerable Rubies ... they'll never upgrade.
For a full list (my rant on this), see: https://gist.github.com/e2/ac32569852cbd31f7da637500174d907
In practice, the only reason to support "backward compatibility" is to ... prevent people from being frustrated that their Travis builds are breaking. But the elephant in the room is: all because a Travis build is green on e.g. Ruby 1.9.3, it doesn't mean that projects/gem's dependencies support Ruby 1.9.3. That's because SemVer doesn't require major bumps when dropping support ... and people aren't making their gems require the supported versions of Ruby.
If your project depends on e.g. "foo", and "foo" doesn't test 1.9.3 on Travis, that means it isn't supported. So what use is declaring support for Ruby 1.9.3 if you're not locked to dependent gems that GUARANTEE they work on 1.9.3? And the same goes for dependencies of dependencies. If one dependency is "too relaxed", you'll get a passing Travis build and a crash in production.
There's neither a need nor a single valid reason to support more Rubies other than those supported by Ruby core team. And that's 2.2.4 at least (for security reasons) and 2.3.1 (just released).
I haven't even touched the subject and I'm already ranting...
In short: a working Travis build on a given Ruby version only guarantees that YOUR project's code works on that version of Ruby and for the Gemlock file you have. (For gems, if they don't have a Gemlock file, then they're just coasting off of whatever gem versions Bundler installed at the moment of building - which could've been months ago if there were no new commits there).
There's just an avalanche of practical reasons to "not support older Rubies". And not a single in favor. (If you dig deep enough).
We've all been taught that "backward-compatibility is important". And it has become: "let's support Ruby 1.8.7 until the end of time". And pretty much 99.9999% of any codebase out there is still Ruby 1.8.7 compatible. And so everyone attempting to use a non-Ruby 1.8.7 feature is usually "punished" based on the dogma of "supporting backward compatibility is important".
Backward compatibility became a "first class citizen". Instead, it should be a well-justified cost.
In terms of SemVer, the whole idea of allowing the exact same codebase to work on multiple versions of interpreters is ridiculous. Ruby is so flexible, it can be done. But that doesn't mean it should be.
The only 2 "sane" examples of supporting an older Ruby that I can think of are: RSpec and MRuby. RSpec, because it's technically a "project-upgrade-helping tool" and MRuby because it's so limited for embedded situations.
Otherwise, the solutions are: upgrade Ruby or don't upgrade Listen. Or upgrade bundler to 1.12.x (not released yet) which will solve that automatically.
Wait a minute, what makes you think Ruby 2.1 is no longer supported? It looks like security fixes will still be backported.
@mvz - "support" means "fixing bugs". Not fixing bugs means: no support.
Security patches are just to keep old services running without getting hacked until they're upgraded. Those services can still start crashing due to a never-to-be-fixed bug, so it just shows how overdue the upgrade is.
Also, security fixes are patch-level changes. Switching from Listen 3.0 to Listen 3.1 is not a patch level change. So, people desperate to "keep old things running until we upgrade" should NEVER upgrade any gem above a patch level upgrade.
If you want services running on an old Ruby it's EXTREMELY risky to upgrade ANYTHING.
In short: people should ask for backporting fixes and security patches. The Ruby core team is nice enough to sometimes comply beyond what they promised. But that's not "support". That's "being nice".
Ruby < 2.2 is basically buggy by definition. Those bugs will never be fixed. Thus, "not supported".
(You can check the changelogs between versions - you'll see plenty of bugs that were never backported).
Supporting Ruby < 2.2 is dragging a dead man through the desert just to bury him somewhere else. It helps no one, it doesn't even make the family happier at the funeral (usually). It's an act of "impractical" kindness, not an "entitlement". Even if, it's up to the family (or insurance company) to pay for bringing the dead home.
Same thing here: Ruby < 2.2 is dead. No matter how many people wish otherwise. If people in the community want to play Frankenstein, it's unfair to everyone else to fund these ridiculous "experiments".
@e2 thanks, that's a very clear write-up!
@mvz - thanks for letting me know it's clear! After so many discussions, I'm still feeling I'm not communicating things clearly and properly.
I added 2 more "myths" (based on more conversations).
I think maintainers who have a gem in "maintenance mode" (as opposed to "active development") should be a lot more conservative about locking.
E.g. foo ~> 3.4
is a bad idea because it's too risky, while foo ~> 3.4.5
prevents surprises while still allowing security fixes and bug fixes. If a gem is in maintenance mode, it doesn't need "API" improvements such as new features, etc. So locking to just the minor is too relaxed at best, and too risky in most cases. (Especially nowadays where lots of gems are "silently" dropping support for various Ruby versions already, notably 1.8.7, 1.9.2, 1.9.3 and 2.0).
So you may want to really check (and lock down) your dependencies if you really rely on a specific or outdated Ruby (to avoid breakage on production systems). Listen is safe, because it at least won't let you install it on the wrong Ruby.
Does anyone use guard-listen in production? This seems all a little OTT.
@toxaq - some people use Listen on servers to handle uploaded files, some use it for synchronizing and Listen is used by Vagrant AFAIR.
Rails 5 will only support Ruby >= 2.2, so it's not far fetched to drop anything below. Guard is heavily used for Rails projects specifically, and upgrading servers to avoid vulnerabilities is recommended.
The only real "issue" is that people act as if upgrading Ruby is more inconvenient than it really is, while there's no "payoff" in postponing an upgrade.
I think the real issue is that developers often aren't in the position of just changing the production ruby version whenever they want. Now having locked in a listen version to allow bundle install to continue, there are no warnings and, worse, no possibilities for upgrades to remind me.
It would seem to be a better option to log a warning every time an unsupported ruby is run. Giving someone a regular call to action would seem more beneficial in achieving the goal than having them entirely bypass the mechanism you're employing.
I think the real issue is that developers often aren't in the position of just changing the production ruby version whenever they want.
They should be. I'm open to the idea that there's a business case for not upgrading, but the only one I can think of is: upgrading from Ruby 1.8.7 to 1.9.3. Mostly because of hash ordering that can create obscure time consuming bugs. So that needs more time and more planning.
Now having locked in a listen version to allow bundle install to continue, there are no warnings and, worse, no possibilities for upgrades to remind me.
If you lock a major version, that's the idea since you want to lock to an API. If you lock the minor, you're pretty much in "backward compatibility mode", which means you're agreeing to the costs and you have to actively track the project. It means the responsibility is 100% yours - which includes asking for backporting. If you're a paid customer, you expect the company maintaining the project to support existing customers if they have trouble upgrading.
I've noticed how the RSpec guys (and maintainers of other projects) often bend over backwards to support some old code no one uses. E.g. I just "wasted" time doing the groundwork for glob support in Guard - which mean "maintaning support" for deprecated functionality and covering it with unit tests. A waste of time, but that's too bad.
You're right about not being reminded. I created https://github.com/e2/ruby_dep just for this (it shows warnings about vulnerable Ruby versions at least - so updating just that gem updates the warnings).
It would seem to be a better option to log a warning every time an unsupported ruby is run.
This is exactly what RubyDep does. I got a lot of flack for it though (that Listen shouldn't be responsible for warning about vulnerable Ruby versions). So I'm hesitating on doing something similar for gems.
Giving someone a regular call to action would seem more beneficial in achieving the goal than having them entirely bypass the mechanism you're employing.
In theory, deprecations should be the "early warning" about moving to a new major version.
Here, the situation is different: Listen 3.x wasn't meant to be supported on older Ruby versions. It was my fault that I introduced the problem (didn't get all the version numbers matching everywhere while releasing 3.0), but that doesn't meant I should've left if unfixed. The fix was officially dropping support and being open to backporting if I was presented with a valid use case.
Also, tools like Bundler should be "smarter" with how they resolve dependencies. But Bundler won't be improved without uses cases and bug reports.
We live in a good world now that we have dependency install problems instead of crashes.
That's progress we don't appreciate.
You obviously feel very strongly about this.
@toxaq - yes, I do. Mostly because of 2 things:
Just show a warning to avoid further SemVer discussions.