It's scarily common for organizations to be running ancient versions of Rails in production. At my last gig we spent six months upgrading a Rails 2.3 application to 3.2 and before that I was working with a team that was maintaining an application written in Rails 1x. Kudos to GitHub for sharing this, I really hope they do future posts going into more detail. In my experience one of the hardest aspects to upgrading Rails is that so much of the really useful information has either fallen out of Google or succumbed to link rot.
My current company doesn't even lock most of their dependencies. At first I thought it was crazy (and it is crazy) but it does mean we address compatibility issues immediately. We are mostly running background jobs though so it's safer than anything customer facing
My opinions on this have changed a lot over the past few years. At this point, I think anything that pins dependencies to specific versions is asking for long-term maintainability nightmares. Updates of your dependencies, operating system, language version, etc. should happen weekly, and any instance where you have to pin a dependency to an old version (e.g., a major version release that has some compatibility issues) should be dealt with ASAP.
Obviously this isn't a tenable position in every circumstance, but I think it should be the default. Particularly in a world where the vast majority of security fixes go without an announcement or CVE.
Better idea: if you release rarely enough, pin your dependencies, but upgrade them automatically after each release. This way you will have time to test and fix any breakages before the next release.
The longer you wait, the harder it is. & you don't want to block a release on dependencies. So unless you're not doing development on the application every week, it's simple enough to update every Monday while getting over the fact that the weekend wasn't long enough
I'd wager that less than 5% of your language dependencies bother to issue CVEs when they release security fixes. They get a bug report, fix the problem, and carry on with their life. This also happens all the time with bugs that nobody realizes are security vulnerabilities, because they're "just" crash on invalid input bugs.
Isn't that similar to golang's (now deprecated) stable HEAD philosophy? On larger projects with tons of human resources that works out OK, but for a smaller team wouldn't living on the bleeding edge & dealing with every issue be a ton of work?
The only times I've ever run into issues updating dependencies (other than across major version upgrades of deeply-integrated deps) is when people have put it off for months or more.
Most updates aren't breaking. The overwhelming majority of updates that are breaking are trivially discovered and fixed with one or two tweaks. Almost all the rest can be fixed with a single search/replace.
Being eight minor versions (or two major versions) behind and having to find and fix all of these at once is when people land themselves into trouble.
It’s not, really. Getting there from a long listed of pinned deps can be hard, but staying there is easy
If you update regularly and have decent tests, it’s easy to find and isolate the problem. And if it’s more than you can fix that day, pin it for now and try again later.
I like to pin dependencies but upgrade them weekly with CI. All my tests get ran and a PR is created automatically. This gives us both stability and visibility with the trade-off of more upfront work to get the automation going.
It's not just Rails, this common with many frameworks and even turnkey solutions from vendors. Nothing will ever meet your needs 100% and so you end up with some customization. It really depends on how integral those customizations were and how tightly they are coupled to the product being used.