Commit 3868825
fix(prerelease): unlink names the lockfile residue it cannot repin away (#336)
Reported against 0.24.0-rc.5 by an adopter verifying the #330/#323/#334 fixes. A regression
the #330 fix introduced, and the detector was already catching it correctly — what was
missing is that nothing told the user the fix is one install command.
WHAT BROKE. `link` correctly stopped deleting lockfiles (#330: a deletion is a destructive
edit to committed state unlink cannot undo, and it turns a targeted pin into a full
re-resolve, so an RC evaluation ends up testing "does the RC work" and "does a fresh
resolve work" in one diff). But `unlink` repins MANIFESTS only. A kept lockfile keeps its
`-rc` versions and private-registry tarball URLs, and `npm ci` resolves straight from the
lockfile — so a committed lockfile in that state sends every other machine and every CI run
to a registry it cannot reach. Closing one hole opened another; before #330 this state was
unreachable because the lockfile was gone.
The detector caught it. `unlink` then reported "left pre-release references behind — fix
them before pushing", which is true, unhelpful, and reads like a defect in the tool rather
than a remaining step.
`unlink` now names the offending lockfiles BEFORE running the detector, so the detector's
verdict reads as confirmation rather than a mystery, and prints the reconcile command per
ecosystem. The failure message says the lockfile is the residue and what to run.
IT STILL DOES NOT RUN INSTALLS, and that is deliberate rather than laziness: an install is
network-dependent and can fail, and running the wrong one silently migrates a project's
package manager — which is the exact hazard `npm_manager_for` already exists to avoid. So
the command is derived per install root from that root's own lockfile and PRINTED. Extended
to every ecosystem whose lockfile `link` used to drop, not just npm: uv, poetry, pipenv,
NuGet.
The residue check reads `PRERELEASE_RE` OUT OF THE DETECTOR rather than restating it. A
second copy of that regex would drift, and this function exists precisely to explain the
detector's own verdict — the two disagreeing would be worse than not explaining it at all.
ALSO FIXED, and it is the part that misleads at the worst moment: the detector's remediation
text still said unlink "drops the lockfile". It has not since #330, so the tool was telling
the user something untrue exactly when they were trying to work out why it failed. It now
states that unlink does NOT touch the lockfile and that repinning therefore cannot clear a
reference inside one.
Verified against a reproduction of the reported state (manifest repinned, lockfile still on
rc.5 with a private tarball URL): unlink names `package-lock.json`, prints `npm install`,
repins the manifest to 0.23.2, leaves the lockfile untouched, and exits non-zero with the
actionable message. CONTROLLED against an already-reconciled lockfile, which unlinks clean
with no residue reported — a false positive here would be worse than the bug, since it would
teach adopters to ignore the one check that prevents shipping a private-registry lockfile.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent c4f995f commit 3868825
2 files changed
Lines changed: 75 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
355 | 355 | | |
356 | 356 | | |
357 | 357 | | |
358 | | - | |
359 | | - | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
360 | 365 | | |
361 | 366 | | |
362 | 367 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
291 | 291 | | |
292 | 292 | | |
293 | 293 | | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
294 | 345 | | |
295 | 346 | | |
296 | 347 | | |
| |||
574 | 625 | | |
575 | 626 | | |
576 | 627 | | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
577 | 639 | | |
578 | | - | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
579 | 646 | | |
580 | 647 | | |
581 | 648 | | |
| |||
0 commit comments