Skip to content

prerelease-link.sh: repinning a tracked package.json prints no "committable" warning, unlike pyproject.toml/pom.xml #338

Description

@dmealing

Found while evaluating the 0.24.0-rc.* line in an adopter project — the same evaluation that produced #323, #324, #325 and #330.

link warns you when it writes to a file that is tracked by definition and therefore cannot be hidden in .git/info/exclude:

! pyproject.toml is tracked by definition — the managed block is committable; 'unlink' removes it
! pom.xml is tracked by definition — the managed block is committable; 'unlink' removes it

package.json is equally tracked by definition, is repinned by the same run, and gets no such warning. repin_npm finishes with a bare count:

  repinned 12 @metaobjectsdev/* dependencies to <version> across 3 manifest(s)

Verified on current main (f5913cedc): repin_npm ends at say "repinned $total …" with no tracked check, while the pyproject.toml and pom.xml warnings sit at lines 466 and 534.

Why this is worth a warning and not just tidiness

It leaked to a shared branch twice, in one repository, in two different manifests, from two unrelated commits. Both times the mechanism was identical: link repinned a tracked package.json during pre-release testing, and the repin rode along in a commit about something else. Six version-string lines in a large diff read as noise, and neither leak was caught in review.

The consequences differed only in how long they hid:

  • one surfaced when an install failed — the manifest named a pre-release iteration that had since been superseded and removed from the private registry, so it resolved from nowhere: not public, not private. pnpm install --frozen-lockfile (true by default in CI) failed with six specifier mismatches, because the lockfile had never been regenerated and still named the public version.
  • the other sat on the default branch for weeks, in a second manifest, undetected. It was found only by running detect-prerelease-pins.sh by hand — after the first had already been fixed, by someone who assumed the first was the only one.

That second point is the argument. The repo had four other artifacts still naming the public version (the lockfile, a sibling manifest, a CI workflow pin, and the committed codegen), and none of them made the divergence visible. A per-file warning naming the manifest is what a reviewer would have had to skim past deliberately.

The global warning does not cover this

link already ends with:

! this project now depends on artifacts that exist ONLY on the private registry.
! run 'unlink' before pushing anything from it.

That is a statement about the project. It is printed once, before the developer starts the work they actually linked in order to do, and it names no file. The pyproject.toml/pom.xml warnings are different in kind — they name the specific artifact that will end up in git status, which is the thing a reviewer sees.

Suggested fix

Have repin_npm warn per tracked manifest it rewrites, in the same register as the other two:

! <path>/package.json is TRACKED — the repin is committable; 'unlink' reverts it

One line per manifest is noisier than a count, but that is the point: the count is what made the leak invisible. The path is what makes it reviewable.

Adjacent, possibly worth folding in

detect-prerelease-pins.sh found both leaks instantly, once run — including one that had been on the default branch for weeks. But it is installed by link and described as something to commit and run in CI, which is guidance an adopter reads while linking and acts on later, if at all. Wiring it in at link time (or making link refuse to finish until it is gated) would close the loop the two warnings above only narrow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions