Skip to content

Check engines.node against every locked package in CI - #722

Open
barborico wants to merge 2 commits into
mainfrom
brynna/check_node_engines
Open

barborico wants to merge 2 commits into
mainfrom
brynna/check_node_engines

Conversation

@barborico

@barborico barborico commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds a CI check that fails when package.json's engines.node admits a Node version that some package in package-lock.json doesn't support.

Urgency: LOW
Expected review effort: LOW

Motivation

npm compares a package's engines only with the Node that runs the install. CI therefore stays green on the versions it runs, while the root engines.node keeps advertising versions a dependency has dropped. That's how #704 came to need a review comment: jsdom 30 needs ^22.22.2 || ^24.15.0 || >=26.0.0, and the root still said >=22.22.1. A check catches this on the Dependabot PR that raises the floor, so nobody has to notice it in review.

Description of Changes

  • scripts/check-node-engines.js: reads the root engines.node from package.json and every locked package's engines.node from package-lock.json. It fails, listing each package and its range, when the root range isn't a subset of a package's range (semver.subset). A range semver can't parse is skipped with a warning.
  • npm run check:engines: runs the script. The node-lint job runs it after npm ci.
  • semver devDependency (ISC): the hoisted copy in the tree is 6.3.1, which has no subset(), and any other bump could change it.
  • .claude/access-dev-testing.md: documents the check and what to do when it fails.

Validation of Changes

Guidance for Reviewers

  • The check is strict on purpose. A root range that admits even one minor version a dependency excludes fails.

🤖 Generated with Claude Code

npm compares a package's engines only with the Node that runs the
install, so CI stays green on the versions it uses while the root
engines.node keeps advertising versions a dependency has dropped.
scripts/check-node-engines.js fails when the root range isn't a subset
of each locked package's range, and node-lint runs it after npm ci.

The check's first finding is main's own range: >=22.22.1 admits Node 23,
which vitest excludes, and Node 23.0-23.1, which the Sentry SDK
excludes. engines.node narrows to ^22.22.1 || >=24.0.0, the
intersection. semver becomes a direct devDependency because the hoisted
copy is 6.x, which has no subset(), and could change under any bump.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@barborico
barborico marked this pull request as ready for review October 28, 2026 00:59
Jeff-Rowell
Jeff-Rowell previously approved these changes Oct 28, 2026
…ines

# Conflicts:
#	package-lock.json
#	package.json
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.

3 participants