4 ms·
I'm curious: When updating packages, say NPM packages, what are your practices? For us, we audit every update of every package. We read the changelog or releas
by HellsMaddy 3y ago
I'm curious: When updating packages, say NPM packages, what are your practices?
For us, we audit every update of every package. We read the changelog or release notes for every version from the current version to the new version (some packages make this very cumbersome, looking at you Vercel). Then, we use our judgement about the order in which to update packages; usually we apply all patch-level updates, run our tests; then minor updates, re-run our tests; and then we apply major updates one-by-one and re-run tests after each of them.
We've found plenty of semver violations in this process, to the point where we don't really trust the semver of NPM packages at all.
Is this a common approach, or do you just blindly update everything at once and fix things if they break?
- obi1kenobi 3y agoSpeaking for myself in Rust, I blindly update everything and fix what's broken. My projects tend to have substantial test suites, so if the compiler thinks it's fine and the tests think it's fine, it's probably fine. Sometimes it isn't fine, of course. Those cases fortunately are few enough and not damaging enough that this approach hasn't been that problematic thus far.
- contextnavidad 3y agoUpgrade everything you need with a commit per upgrade, then if something breaks `git bisect` to find the troublesome package. And read release notes for everything you upgrade too.
- stevepike 3y ago(disclaimer - I'm the founder of infield.ai; we're software for upgrading dependencies safely, even when there are breaking changes). I spent most of last year upgrading large Rails/React apps as a consultant so I have lots of thoughts on this. In general companies are in one of two states - deep in a hole of technical debt, or in a good place and trying to stay relatively up-to-date. Most established JS/Ruby codebases I've seen have dependency technical debt and they _know_ they're going to run into breaking changes trying to upgrade. These companies need to do the project management work to break their debt down into as many small incremental changes as they can. Any upgrade that has a breaking change gets done standalone (you need to read the changelog to figure out if there's a breaking change, you don't trust semver). Upgrades that are necessary but safe can be batched together. When you have to make code changes for breaking changes these should also get done incrementally ahead of time. Usually these changes are backwards compatible (e.g., if a deprecated method is going away in v2.0, you can switch to the new method in v1.X so you're not upgrading the package and changing your code in the same PR). Even if they're not trivially backwards compatible you can often make them so, and you should. I've done individual upgrades consisting of dozens of small pull requests. When you do it this way you don't get stuck with a long-running branch that gets abandoned, you roll back fewer deploys, and changes are easy to review. Once you're on the latest major version of all your packages then you want to get into an ongoing cadence of dependency maintenance. Good small-medium teams tend to do a maintenance rotation where you spend ~1 day/sprint of one developer's time on this upgrade work. Here project management is also important - ideally someone is looking at CVEs, stale packages, and other indicators of package risk, reading changelogs to identify effort, and breaking out maintenance tickets. Some of these tickets will be individual package upgrades, some will be batches of safe upgrades, and some (when a new major version of a framework comes out) will get treated like the previous paragraph. Larger teams might consolidate this work in a platform engineering team, but that has its own organizational challenges.