Skip to content

fix(fleet-bump): honour engines.npm per app + guard a re-resolved lock - #534

Merged
rubenvdlinde merged 1 commit into
mainfrom
fix/fleet-bump-honour-engines-npm
Aug 21, 2026
Merged

fix(fleet-bump): honour engines.npm per app + guard a re-resolved lock#534
rubenvdlinde merged 1 commit into
mainfrom
fix/fleet-bump-honour-engines-npm

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

The first real run of fleet-shared-dep-bump.yml (docudesk #710) produced an 84-add / 16-delete package-lock.json diff for what should be a 3-line version bump.

Measured, both directions, on that exact lockfile pair

npm packages added removed dev flag flips line diff
10 (setup-node bundles this with Node 22) 0 0 81 +84 / -16
11 (what every sampled app declares) 0 0 0 +3 / -3

The dependency tree never changed. npm 10 just classifies it differently: 81 @esbuild/* platform binaries gained "dev": true, while esbuild itself stayed unflagged.

Every app sampled — docudesk, launchpad, portaliq, openregister, hermiq, pipelinq, nldesign — declares engines.npm: ^11.0.0.

Why it slipped through

This is the trap release.yml already hit and fixed in #525: setup-node installs the npm bundled with Node, not the one the repo asks for. release.yml reads ./package.json once because it runs inside a single repo. This workflow walks 21, so the range has to be re-read and re-honoured inside the loop. The global install is cached per distinct range, so the fleet as it stands costs one npm i -g.

Second, independent check

Fixing the toolchain alone would leave nothing to catch the next variant. So: a lock-only bump of one package must not add packages, remove packages, or flip an unrelated package's dev flag. If it does, the tree was re-resolved rather than nudged — the npm side is reverted and annotated instead of opening a PR nobody can review. The composer bump still proceeds.

Both controls exercised, so this is a check that demonstrably can fail:

  • must-fail — known-bad npm-10 lock → 81 flips → guard fires ✅
  • must-pass — correct npm-11 lock → 0 flips → guard silent ✅

docudesk #710 will be closed and re-cut once this lands.

…esolved lock

The first real run of this workflow (docudesk PR #710) produced an 84-add /
16-delete package-lock diff for what is a 3-line version bump.

MEASURED, both directions, on that exact pair of lockfiles:

  npm 10 (what setup-node bundles with Node 22):
    packages added 0, removed 0 -- but 81 `@esbuild/*` platform binaries
    newly marked `"dev": true`, while `esbuild` itself stayed unflagged.
  npm 11 (what every sampled app declares, `engines.npm: ^11.0.0`):
    packages added 0, removed 0, dev-flag changes 0, diff exactly +3/-3.

So the tree never changed; npm 10 simply classifies it differently. This is
the same trap release.yml already documented and fixed in #525 -- setup-node
installs the npm BUNDLED WITH NODE, not the one the repo asks for. release.yml
reads ./package.json once because it runs inside one repo; this workflow walks
21, so the range is re-read and re-honoured inside the loop, with the global
install cached per distinct range (one install for the fleet as it stands).

Adds a second, independent check so a wrong toolchain cannot quietly ship
again: a lock-only bump of ONE package must not add packages, remove packages,
or flip an unrelated package's `dev` flag. If it does, the tree was
re-resolved rather than nudged -- the npm side is reverted and annotated
rather than opened as a PR nobody can review. Verified to FAIL on the known-bad
lock (81 flips) and to PASS on the correct one (0 flips), so it is a check that
demonstrably can fail.
@rubenvdlinde
rubenvdlinde merged commit 573b65e into main Aug 21, 2026
36 checks passed
@rubenvdlinde
rubenvdlinde deleted the fix/fleet-bump-honour-engines-npm branch August 21, 2026 09:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant