Choosing between nest update CLI and manual package.json edits for deterministic rollback after a failed NestJS major upgrade
0 reputation · 27 Feb 2021, 00:35 UTC
0 reputation · 27 Feb 2021, 00:35 UTC
The goal is to guarantee a reversible upgrade path when a NestJS major release alters decorator signatures or DI configuration, allowing teams to restore the pre‑upgrade state without losing uncommitted work.
The nest update CLI speeds up dependency resolution to the latest compatible versions but provides no built‑in mechanism to revert transitive changes, forcing developers to rely on external version‑control or lockfile strategies. Manually editing package.json and running npm install gives explicit control over each version, enabling selective adoption and easier source‑control rollback, yet demands precise pinning and may overlook environment‑specific artifacts or peer‑dependency conflicts that only surface at runtime.
What trade‑offs determine whether to prefer the nest update CLI or manual package.json pinning for safe rollback? Can lockfile‑based strategies (e.g., npm ci) reliably complement the CLI to recover a known good state? Does manual version pinning consistently expose all transitive dependency conflicts before they affect the application?
27025 reputation · 27 Feb 2021, 10:46 UTC
To guarantee a reversible upgrade path, the safest approach is to commit the pre‑upgrade state, use a lockfile, and rely on npm ci (or yarn install --frozen-lockfile) to restore the exact runtime environment. The choice between nest update and manual package.json edits only affects how you reach that state, not the rollback mechanism itself.
package.json and updates internal files in a single step. It saves time but can silently bump transitive packages that are not listed explicitly, which may introduce subtle incompatibilities that only surface at runtime.npm install to surface peer‑dependency conflicts, but you can review the diff before committing.When a lockfile (e.g., package-lock.json for npm) is committed, npm ci will recreate the exact dependency tree that existed at the time of the commit. This works for both CLI‑driven and manual upgrades: after a failed upgrade, simply revert the commit and run npm ci to return to the pre‑upgrade state.
Editing package.json manually does expose peer‑dependency mismatches at install time because npm install (or yarn install) will validate the entire tree. However, it can miss conflicts that only become apparent when a library is executed in a particular runtime context. Therefore, after any manual edit, you should run the full test suite to surface such issues before committing.
package.json and lockfile:git add package.json package-lock.json
git commit -m "Pre‑upgrade: NestJS 7.x"
nest update @nestjs/core @nestjs/common @nestjs/platform-express --force (add --force only if you explicitly want to ignore peer warnings).package.json to the desired major versions, then npm install.npm test
git checkout HEAD~1 -- package.json package-lock.json
npm ci
npm list @nestjs/core @nestjs/common @nestjs/platform-express
If you discover that the upgrade requires a non‑standard patch or that a third‑party library has its own breaking change that cannot be satisfied by any single major version of NestJS, you may need to adopt a more granular approach (e.g., pinning specific transitive dependencies). In that case, you would ask:
Do any of the dependent libraries (e.g.,@nestjs/microservices,@nestjs/graphql) have their own major‑version constraints that conflict with the target NestJS release?
Use comments to ask for clarification. Post a solution as an answer.
27,025 reputation · 27 Feb 2021, 05:12 UTC
While the choice between the CLI and manual edits determines how dependencies are bumped, a critical distinction is that nest update often triggers schematics. These are automated code transformations that modify your TypeScript files to match new API signatures.
If an upgrade fails, reverting package.json and the lockfile via npm ci restores the environment, but it does not undo these structural code changes. To ensure a truly deterministic rollback, teams should:
Without this separation, you may find yourself in a state where the dependencies are reverted to the old version, but the source code remains transformed for the new version, leading to compilation errors.