Skip to content

ci: check the package on its minimum Node.js version - #31

Closed
Kikobeats wants to merge 1 commit into
masterfrom
Kikobeats/ci-engines-floor
Closed

Kikobeats wants to merge 1 commit into
masterfrom
Kikobeats/ci-engines-floor

Conversation

@Kikobeats

@Kikobeats Kikobeats commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Adds .github/workflows/engines.yml, which checks that every published package installs and loads on the lowest Node.js version its engines.node allows. A dependency bump or new syntax that raises the real floor now turns CI red instead of breaking users on that version.

What it does

  1. Pack (Node LTS). pnpm install, then for each non-private workspace package (the root package in a single-package repo): run prepublishOnly if present, and pnpm pack it. The floor is read from that package's engines.node at run time. Nothing is hardcoded in the workflow. A range that is not >= x fails the job.
  2. Floor (one matrix job per package, on that floor). In an empty directory, npm install --engine-strict of the package tarball, plus the tarballs of the workspace packages it depends on. This is what a user does: production dependencies only, lifecycle scripts included. Any package in the tree whose engines excludes the floor fails the install with EBADENGINE. Without --engine-strict, npm only warns.
  3. Load. require every runtime entry in exports (or main when there is no exports). Entries that are import-only fall back to import(). Type-only entries and * patterns are skipped.

It runs as its own workflow on pull_request and on push to the default branch, so the release logic in main.yml is untouched.

Why npm on the floor side

pnpm needs Node 18 or later, so it cannot run on older floors, and npm ships with every Node.js version. The install happens in a fresh directory from tarballs, so devDependencies never enter the tree and the test toolchain (ava, c8, standard), which needs a newer Node, is not involved.

Limits

  • setup-node resolves a major-only floor such as >= 20 to the latest 20.x. The job cannot tell 20.0 from 20.12. A floor written with a minor, such as >= 20.19, is checked at the latest 20.19.x.
  • Loading an entry point runs its top-level code only. A dependency required lazily inside a function is covered by the engines check, not by the load.
  • bin scripts are not executed.
  • For a caret or tilde range, npm installs the newest version whose engines accept the running Node. A user on the floor can get an older dependency than a user on current Node, and the job checks the tree the floor user gets. It goes red only when no version in range supports the floor, which is the case that breaks users.

Proof that it catches a violation

On microlinkhq/keyvhq#294, @keyvhq/redis declares >= 20 and depends on ioredis@6, which requires >=20.0.0. A throwaway commit lowered @keyvhq/redis to >= 18:

  • Run with >= 18: Node 18 @keyvhq/redis fails, the other 15 packages pass.
    npm error code EBADENGINE
    npm error notsup Not compatible with your version of node/npm: ioredis@6.0.0
    npm error notsup Required: {"node":">=20.0.0"}
    npm error notsup Actual:   {"npm":"10.8.2","node":"v18.20.8"}
    
  • Run with the real >= 20, after dropping that commit: all 16 jobs pass.

🤖 Generated with Claude Code


Note

Low Risk
Adds CI-only workflow and scripts with no runtime or production code changes.

Overview
Adds a dedicated engines GitHub Actions workflow (PRs and pushes to master) so CI fails when a published package cannot actually run on the Node version its package.json claims.

A Pack job on Node LTS discovers non-private workspace packages, enforces engines.node as a >= x floor, runs prepublishOnly and pnpm pack, builds a matrix of each package plus its workspace dependency tarballs, and uploads artifacts. Floor matrix jobs install that closure with npm install --engine-strict on the declared floor Node (npm is used because pnpm cannot run on older floors), then smoke-load every runtime exports entry via require/import().

Release logic in other workflows is unchanged; this is additive CI coverage for engine mismatches and broken entry points on minimum supported Node.

Reviewed by Cursor Bugbot for commit f0d6268. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 38 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c4c8521c-d718-439a-b815-1327ad1ddda3
Commits

Reviewing files that changed from the base of the PR and between ab4f624 and f0d6268.

Files selected for processing: 1
  • .github/workflows/engines.yml

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 006b7a9f-2467-4cc2-a460-de0ebeb4cd95
Commits

Reviewing files that changed from the base of the PR and between cb471db and ab4f624.

Files selected for processing: 1
  • .github/workflows/engines.yml

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The new GitHub Actions workflow runs on pull requests and pushes to master. It packages non-private workspace packages, then installs and smoke-tests each package on its declared Node version floor.

Changes: Node engine checks

Layer / File(s) Summary
Package tarball preparation
.github/workflows/engines.yml
The workflow validates package Node engine floors, runs available prepublishOnly scripts, packs packages with their transitive workspace dependencies, and uploads the tarballs.
Floor installation and entry-point checks
.github/workflows/engines.yml
A matrix job installs each package and its dependency tarballs with npm --engine-strict, then tests exported entry points on the declared Node floor. The smoke test tries require first and uses dynamic import for the specified import-only errors.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Workflow as engines.yml
  participant pnpm
  participant Artifact as GitHub artifact
  participant npm
  participant Node as Node runtime
  Workflow->>pnpm: Install dependencies and pack workspace packages
  pnpm->>Artifact: Upload package tarballs
  Workflow->>Artifact: Download tarballs for the floor job
  Workflow->>npm: Install package tarballs with engine-strict
  Workflow->>Node: Load exported entry points on the declared Node floor
Loading

Possibly related PRs

  • Kikobeats/https-tls#27: Changes pnpm install behavior using environment variables also set by this workflow.
  • Kikobeats/https-tls#28: Changes package installation behavior that the workflow’s minimum-Node installation checks exercise.
Merge Risk: Minimal · previous review ab4f6

The workflow has no identified issue that needs fixing before merge; normal CI checks remain appropriate.

Pre-merge checks: Passed 4
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title "ci: check the package on its minimum Node.js version" matches the main change. The PR adds a GitHub Actions workflow that packs each non-private package, installs it with npm --engine-stric…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "ci: check the package on its minimum Node.js version" matches the main change. The PR adds a GitHub Actions workflow that packs each non-private package, installs it with npm --engine-strict on the minimum Node.js version from its engines.node range, and smoke-tests its entry points. The title is specific, uses the conventional commit prefix, and fits the changeset. The PR objectives confirm the same goal.

Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https-tls

Details
Benchmark suite Current: f0d6268 Previous: cb471db Ratio
sortHeaders chrome 109.5 ms (102.8-110.3) 104.7 ms (103-108.3) 1.05
sortHeaders firefox 93.6 ms (90.1-95.5) 90.6 ms (89.7-94.4) 1.03
sortHeaders safari 89 ms (87.3-92.4) 88.4 ms (86.6-91.7) 1.01
getBrowser top 100 user agents 333.1 ms (323.8-338.5) 326.8 ms (324.1-335.4) 1.02
tls options top 100 user agents 277.1 ms (259.5-283.5) 259.6 ms (259.5-289.5) 1.07

This comment was automatically generated by workflow using github-action-benchmark.

@coveralls

coveralls commented Oct 29, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 40846931071

Warning

No base build found for commit cb471db on master.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 99.653%

Details

  • Patch coverage: No coverable lines changed in this PR.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 248
Covered Lines: 248
Line Coverage: 100.0%
Relevant Branches: 40
Covered Branches: 39
Branch Coverage: 97.5%
Branches in Coverage %: Yes
Coverage Strength: 11.25 hits per line

💛 - Coveralls

@Kikobeats
Kikobeats force-pushed the Kikobeats/ci-engines-floor branch 2 times, most recently from 7714b2b to 21e7bb5 Compare October 29, 2026 09:02
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Kikobeats
Kikobeats force-pushed the Kikobeats/ci-engines-floor branch from 21e7bb5 to f0d6268 Compare October 29, 2026 09:05
@Kikobeats

Copy link
Copy Markdown
Owner Author

Closing: not pursuing the floor CI job.

@Kikobeats Kikobeats closed this Oct 29, 2026
@Kikobeats
Kikobeats deleted the Kikobeats/ci-engines-floor branch October 29, 2026 09:34
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.

2 participants