Skip to content

feat: add --no-runtime to skip installing runtime entries#11557

Merged
zkochan merged 6 commits into
mainfrom
no-runtime-flag
May 9, 2026
Merged

feat: add --no-runtime to skip installing runtime entries#11557
zkochan merged 6 commits into
mainfrom
no-runtime-flag

Conversation

@zkochan

@zkochan zkochan commented May 8, 2026

Copy link
Copy Markdown
Member

Summary

Adds a --no-runtime flag (config: runtime: boolean, default true) that suppresses install of runtime entries declared via devEngines.runtime (the runtime: protocol) without modifying the lockfile.

The lockfile keeps the runtime entry, so frozen-lockfile validation still passes; only the runtime fetch and .bin linking are skipped. Useful in CI matrices where the runtime is provisioned externally (e.g. via pnpm runtime -g set node <version>) before pnpm install runs.

The existing --runtime-on-fail=ignore is unsuitable for this case: it mutates the manifest and regenerates the lockfile to drop the runtime entry, which trips frozen-lockfile validation. The two flags are orthogonal and serve different purposes.

Implementation

The hook lives in the lockfile filter stage:

  • lockfile/filtering/src/filterImporter.ts — strips runtime: refs from the importer's deps maps when skipRuntimes is set.
  • lockfile/filtering/src/filterLockfileByImportersAndEngine.ts — new skipRuntimes?: boolean option; runtime-protocol direct deps are dropped before they enter pickedPackages, so they never reach the dep graph or bin-linker. Applies to all runtimes (node, deno, bun) since they share the runtime: protocol prefix.

The option is plumbed through installing/deps-restorer, installing/deps-installer, and installing/commands to the user-facing pnpm install --no-runtime flag.

Example

// package.json
{
  "devEngines": {
    "runtime": {
      "name": "node",
      "version": "22.13.0",
      "onFail": "download"
    }
  }
}

Local dev: pnpm install — installs node 22.13.0 as before.

CI matrix entry:

- run: pn runtime -g set node ${{ matrix.node }}
- run: pn install --no-runtime

The lockfile is unchanged; the matrix's externally-provisioned node is used.

Test plan

  • Unit test in lockfile/filtering/test/filterByImportersAndEngine.ts verifying skipRuntimes: true strips runtime: entries from importers and packages while leaving regular deps intact.
  • E2E test in pnpm/test/install/runtimeOnFail.ts that runs pnpm install (downloads node), wipes node_modules, runs pnpm install --frozen-lockfile --no-runtime, then asserts the lockfile importer entry is unchanged and .bin/node is not created.
  • Existing --runtime-on-fail=ignore test still passes (orthogonal semantics preserved).
  • Build clean across all touched packages.

Written by an agent (Claude Code, claude-opus-4-7).

Summary by CodeRabbit

  • New Features
    • Added a --no-runtime (config: runtime=false) option to skip fetching/linking runtime packages while leaving the lockfile intact.
  • Behavior
    • Lockfiles keep runtime entries so frozen-lockfile validation passes; runtime binaries are not installed and runtime entries are excluded from install/prune/filter flows when enabled.
  • Tests
    • New tests cover --no-runtime for reinstall, fresh checkout, and different store settings.
  • Documentation
    • Added a changeset and bumped related package versions.

Review Change Stack

zkochan added 2 commits May 9, 2026 01:32
Lets users skip the install/link of `devEngines.runtime` entries (e.g.
Node.js downloaded via the `runtime:` protocol) without modifying the
lockfile. The lockfile keeps the runtime entry so frozen-lockfile
validation still passes; only the runtime fetch and `.bin` linking are
skipped. Useful in CI matrices where the runtime is provisioned
externally before `pnpm install` runs.
Copilot AI review requested due to automatic review settings May 8, 2026 23:34
@coderabbitai

coderabbitai Bot commented May 8, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f4c7aee-b154-402e-9043-53bbf6c73bd8

📥 Commits

Reviewing files that changed from the base of the PR and between a9c314c and ec9477f.

📒 Files selected for processing (2)
  • installing/deps-installer/src/install/index.ts
  • pnpm/test/install/runtimeOnFail.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • pnpm/test/install/runtimeOnFail.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Agent
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Compile & Lint
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,tsx,jsx}: Use trailing commas in code following Standard Style with modifications
Prefer functions over classes
Declare functions after they are used, relying on hoisting
Functions should have no more than two or three arguments; use a single options object for functions needing more parameters
Organize imports in order: standard libraries, external dependencies (sorted alphabetically), then relative imports

Files:

  • installing/deps-installer/src/install/index.ts
🔇 Additional comments (2)
installing/deps-installer/src/install/index.ts (2)

1374-1387: Runtime entries are correctly excluded from direct bin-linking inputs.

Line 1381–1384 now removes runtime depPaths from dependenciesByProjectId and marks them in ctx.skipped, which correctly prevents runtime bin linking in the direct path.


1440-1440: skipRuntimes is correctly propagated to linkPackages.

This keeps lockfile filtering and package-linking behavior aligned for --no-runtime.


📝 Walkthrough

Walkthrough

This PR adds a --no-runtime flag (config: runtime=false) that skips fetching and linking runtime entries while preserving them in the lockfile; the option is threaded through config, CLI, install/link/prune, restorer, and lockfile filtering, with tests and a changeset.

Changes

Runtime Skip Feature

Layer / File(s) Summary
Configuration Schema & Types
config/reader/src/Config.ts, config/reader/src/types.ts, config/reader/src/configFileKey.ts
Config interface gains runtime?: boolean. pnpmTypes adds runtime: Boolean. excludedPnpmKeys includes 'runtime'.
CLI Option Declaration
installing/commands/src/install.ts
Registers runtime in rcOptionsTypes() allowlist and documents --no-runtime in help text as skipping runtime fetch/link while preserving the lockfile.
Installation Option Threading
installing/commands/src/installDeps.ts, installing/commands/src/recursive.ts, installing/deps-installer/src/install/extendInstallOptions.ts, installing/deps-installer/src/install/index.ts
InstallDepsOptions and RecursiveOptions include runtime from Config. StrictInstallOptions adds skipRuntimes: boolean (default false). Installation converts opts.runtime === false to skipRuntimes passed to installer.
Restorer & Lockfile Filter Integration
installing/deps-restorer/src/index.ts, lockfile/filtering/src/filterLockfileByImportersAndEngine.ts
HeadlessOptions adds optional skipRuntimes. FilterLockfileOptions includes skipRuntimes and propagates it through dependency collection and filtering.
Lockfile Filtering Implementation
lockfile/filtering/src/filterImporter.ts, lockfile/filtering/src/filterLockfileByImportersAndEngine.ts, lockfile/filtering/src/filterLockfile.ts, lockfile/filtering/src/filterLockfileByImporters.ts
filterImporter signature extended with optional opts.skipRuntimes. New helper filters out runtime:-prefixed references. toImporterDepPaths, pickPkgsWithAllDeps, and pkgAllDeps accept and propagate skipRuntimes.
Linking / Prune Integration
installing/deps-installer/src/install/index.ts, installing/deps-installer/src/install/link.ts, installing/linking/modules-cleaner/src/prune.ts
linkPackages and LinkPackagesOptions accept skipRuntimes; prune passes skipRuntimes into filterLockfile. Installer marks @runtime: depPaths as skipped so they are not linked.
Tests & Documentation
lockfile/filtering/test/filterByImportersAndEngine.ts, pnpm/test/install/runtimeOnFail.ts, .changeset/no-runtime-flag.md
Unit test verifies skipRuntimes: true removes runtime: entries from importers and packages. Integration tests confirm --no-runtime preserves lockfile entries while skipping binary installation. Changeset documents the flag and package bumps.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 A flag to skip the runtime dance,
While lockfiles keep their sacred stance,
Through config, CLI, filters deep,
Runtime entries softly sleep,
CI hops on, and builds keep pace.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a --no-runtime flag to skip runtime entry installation, which is the primary feature in this changeset.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch no-runtime-flag

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

@zkochan zkochan added this to the v11.1 milestone May 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new --no-runtime install flag (config key: runtime=false) to skip installing runtime: protocol dependencies (e.g. Node.js via devEngines.runtime) while keeping the lockfile unchanged so --frozen-lockfile validation still passes.

Changes:

  • Add runtime boolean config/CLI support and plumb it through install/recursive flows as skipRuntimes.
  • Update lockfile filtering to drop runtime: refs from importer dependency maps and prevent runtime packages from being picked into the install set.
  • Add/extend unit and E2E coverage for skipRuntimes and --no-runtime.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pnpm/test/install/runtimeOnFail.ts Adds E2E coverage asserting --no-runtime keeps the lockfile entry but skips .bin creation.
lockfile/filtering/test/filterByImportersAndEngine.ts Adds unit test for skipRuntimes filtering behavior.
lockfile/filtering/src/filterLockfileByImportersAndEngine.ts Plumbs skipRuntimes through filtering and excludes runtime: refs from direct dep paths.
lockfile/filtering/src/filterImporter.ts Extends importer filtering to optionally drop runtime: dependencies.
installing/deps-restorer/src/index.ts Threads skipRuntimes into the lockfile filtering stage for headless installs.
installing/deps-installer/src/install/extendInstallOptions.ts Adds skipRuntimes to strict install options and defaults it to false.
installing/commands/src/recursive.ts Plumbs config runtime into recursive install options and maps it to skipRuntimes.
installing/commands/src/installDeps.ts Plumbs config runtime into install options and maps it to skipRuntimes.
installing/commands/src/install.ts Exposes --no-runtime in help text and rc option typing.
config/reader/src/types.ts Adds runtime as a typed boolean config key.
config/reader/src/configFileKey.ts Marks runtime as excluded from global config file keys list.
config/reader/src/Config.ts Adds runtime?: boolean to the Config interface.
.changeset/no-runtime-flag.md Releases changes across affected packages and documents the new flag.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pnpm/test/install/runtimeOnFail.ts Outdated
Comment thread installing/commands/src/installDeps.ts
zkochan added 2 commits May 9, 2026 01:52
Reuses the same lockfile filter so both frozen and non-frozen install
paths share one mechanism. filterImporter now strips runtime: refs from
specifiers as well, so link.ts's specifier-keyed direct-dep linker
naturally excludes runtime entries; filterLockfileByImporters walks the
already-filtered importers, so packages traversal stops at the runtime
boundary too.

Adds an e2e test for fresh-checkout install with --no-runtime.
Copilot AI review requested due to automatic review settings May 8, 2026 23:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.

@zkochan zkochan enabled auto-merge (squash) May 9, 2026 00:27
The lockfile filter handles linkPackages (via filtered specifiers) but
the direct bin-linking call at the end of _installInContext iterates
dependenciesByProjectId and only filters by ctx.skipped. Without this
fix, linkBinsOfPackages tries to link the runtime bin (e.g. node.exe)
from the store. On Linux it silently created a dangling symlink (which
fs.existsSync follows and reports as missing — false-passing the test);
on Windows the linker hardlink/copyFile fallback fails with ENOENT.

Test now uses lstatSync to catch dangling symlinks.
Copilot AI review requested due to automatic review settings May 9, 2026 15:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

reporter: String,
'resolution-mode': ['highest', 'time-based', 'lowest-direct'],
'resolve-peers-from-workspace-root': Boolean,
runtime: Boolean,
@zkochan zkochan merged commit e1e29c1 into main May 9, 2026
17 checks passed
@zkochan zkochan deleted the no-runtime-flag branch May 9, 2026 17:16
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