Skip to content

feat(pacquet): add --ignore-scripts to install#12454

Merged
zkochan merged 2 commits into
mainfrom
feat/pacquet-ignore-scripts
Jun 16, 2026
Merged

feat(pacquet): add --ignore-scripts to install#12454
zkochan merged 2 commits into
mainfrom
feat/pacquet-ignore-scripts

Conversation

@zkochan

@zkochan zkochan commented Jun 16, 2026

Copy link
Copy Markdown
Member

What

Adds an --ignore-scripts flag to pacquet install, mirroring pnpm's flag of the same name.

Why

Since #12436, pacquet install runs the dependency build phase on the fresh-lockfile path. A project with blocked build scripts (e.g. sharp, esbuild, unrs-resolver) therefore fails with ERR_PNPM_IGNORED_BUILDS (exit 1) under the default strictDepBuilds, with no way to install it short of approving every build. pnpm's answer is --ignore-scripts; pacquet had no equivalent (pacquet install --ignore-scripts exited 2 — unknown flag).

This is also what broke pacquet on the vlt.sh benchmark: every fixture (next/astro/svelte/vue/large/babylon) has a package with a blocked build, so pacquet install exits 1, and the benchmark chart marks any non-zero exit as DNF. The benchmark's pnpm command already passes --ignore-scripts; the pacquet command couldn't, because the flag didn't exist. pacquet went DNF across the board starting with 0.11.8.

How

Mirrors pnpm's ignoreScripts semantics:

  • New Config.ignore_scripts field, fed by the --ignore-scripts CLI flag and merged enable-only at the Install dispatch in cli_args.rs (same pattern as --frozen-store).
  • In the during-install build loop (build_one_snapshot), ignore_scripts bypasses the allow-build gate entirely: no script runs and nothing is added to ignored_builds, so the returned set is empty and the strict-mode ERR_PNPM_IGNORED_BUILDS never fires. Patches still apply (pnpm applies a patch even when scripts are suppressed).
  • The project's own lifecycle scripts are skipped too (is_full_install && !config.ignore_scripts), matching pnpm.

This is pacquet catching up to pnpm, which already has --ignore-scripts — no pnpm-side change needed.

Tests

  • build_modules::tests::ignore_scripts_skips_build_without_collecting_ignored — unit test proving the ignored-builds set stays empty (discriminating: the old logic collected the packages).
  • lifecycle_scripts::dependency_build_scripts::install_ignore_scripts_does_not_fail_under_strict_dep_builds — CLI test: install exits 0 under default strict mode, dependency materialized, scripts not run.
  • lifecycle_scripts::project_scripts::ignore_scripts_skips_project_lifecycle_scripts — CLI test: the project's own lifecycle scripts don't run.

just-equivalent checks (fmt, clippy -D warnings, dylint, the affected nextest suites) all pass.

Follow-up (separate repo)

The benchmark itself still needs a one-line change in vltpkg/benchmarks to add --ignore-scripts to BENCH_INSTALL_PACQUET in scripts/variations/common.sh, exactly as the pnpm command already does.


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

Summary by CodeRabbit

  • New Features
    • Added --ignore-scripts CLI flag to suppress lifecycle scripts during installation.
    • Added ignoreScripts support in configuration sources (environment variable and workspace YAML).
  • Bug Fixes
    • Skipping scripts now prevents ERR_PNPM_IGNORED_BUILDS under strict dependency build settings while still materializing dependencies.
    • Project lifecycle scripts are fully suppressed when ignore-scripts is enabled.
  • Tests
    • Added coverage for dependency and project lifecycle suppression behavior.

`pacquet install` runs the dependency build phase on the fresh-lockfile
path (since #12436), so a project with blocked build scripts
(e.g. sharp, esbuild) fails with `ERR_PNPM_IGNORED_BUILDS` under the
default `strictDepBuilds`. pnpm's answer is `--ignore-scripts`; pacquet
had no equivalent, so there was no way to install such a project without
approving every build.

Add `--ignore-scripts`, mirroring pnpm: a `Config.ignore_scripts` field
fed by the CLI flag (merged enable-only at the Install dispatch, like
`--frozen-store`). When set, the during-install build loop bypasses its
allow-build gate entirely — no script runs and nothing is recorded as an
ignored build, so the install no longer fails under `strictDepBuilds`.
Patches still apply, and the project's own lifecycle scripts are skipped
too, matching pnpm's `ignoreScripts`.

This also unblocks the vlt.sh benchmark, whose pacquet command was the
only one missing the `--ignore-scripts` the pnpm command already passes,
making pacquet show up as DNF on every fixture.
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 16, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0)

Grey Divider


Action required

1. Git scripts still run ✓ Resolved 🐞 Bug ⛨ Security
Description
--ignore-scripts is documented to skip lifecycle scripts for dependencies, but git and git-hosted
tarball dependencies still call GitFetcher/GitHostedTarballFetcher with ignore_scripts: false,
so prepare_package() can execute scripts during install even when the flag is set. This defeats
the safety intent of --ignore-scripts and can permit install-time code execution from git-based
deps.
Code

pacquet/crates/cli/src/cli_args/install.rs[R143-154]

+    /// Don't run lifecycle scripts of the project or its dependencies.
+    /// Dependency build scripts that would otherwise be reported as
+    /// ignored are skipped silently, so the install doesn't fail with
+    /// `ERR_PNPM_IGNORED_BUILDS` under `strictDepBuilds`. Mirrors pnpm's
+    /// `--ignore-scripts`.
+    ///
+    /// Merged into `config.ignore_scripts` at the CLI dispatch in
+    /// `cli_args.rs` (it only ever enables, never toggles a yaml `true`
+    /// back off), so the install reads it from the config like every
+    /// other build-script setting.
+    #[clap(long = "ignore-scripts")]
+    pub ignore_scripts: bool,
Evidence
The CLI flag claims to suppress scripts for dependencies, but the install path for git/git-hosted
tarball dependencies explicitly disables the ignore-scripts behavior by passing `ignore_scripts:
false into the git fetchers; those fetchers use ignore_scripts` to decide whether to run
prepare_package() (which runs lifecycle scripts).

pacquet/crates/cli/src/cli_args/install.rs[143-154]
pacquet/crates/package-manager/src/install_package_by_snapshot.rs[368-546]
pacquet/crates/git-fetcher/src/fetcher.rs[148-175]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`--ignore-scripts` currently suppresses dependency build scripts in `BuildModules` and project lifecycle scripts, but **git-based dependency fetching** still runs `prepare_package()` with `ignore_scripts=false`. That means a dependency installed from a git resolution (or git-hosted tarball) can still execute scripts during install, even when the user explicitly passed `--ignore-scripts`.
## Issue Context
- `GitFetcher` / `GitHostedTarballFetcher` already support `ignore_scripts`, but the install dispatcher hardcodes it to `false`.
- The store-index cache key for git-hosted content also encodes a `built` dimension; if you start honoring `ignore_scripts`, make the key consistent (`built = !config.ignore_scripts`) to avoid caching “not-built” content under the “built” key (or vice versa).
## Fix Focus Areas
- pacquet/crates/package-manager/src/install_package_by_snapshot.rs[368-545]
- pacquet/crates/package-manager/src/create_virtual_store.rs[1094-1157]
- pacquet/crates/package-manager/src/create_virtual_store.rs[470-510]
## What to change
1. In `install_package_by_snapshot.rs`, pass `config.ignore_scripts` into:
- `GitHostedTarballFetcher { ignore_scripts: config.ignore_scripts, ... }`
- `GitFetcher { ignore_scripts: config.ignore_scripts, ... }`
2. Update `files_index_file = git_hosted_store_index_key(&package_id, built)` so `built` reflects whether scripts were run:
- `let built = !config.ignore_scripts;`
3. Update warm-prefetch key generation (`snapshot_cache_key`) and its call sites so it uses the same `built` dimension under `ignore_scripts`.
4. Add/extend tests to cover `pacquet install --ignore-scripts` with a git or git-hosted tarball dependency and assert no prepare/build script is executed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Git tarball cache miss 🐞 Bug ➹ Performance
Description
With --ignore-scripts, InstallPackageBySnapshot routes git-hosted tarballs through
GitHostedTarballFetcher using the unbuilt gitHostedStoreIndexKey, but the fetcher’s
ignore-scripts fast-path returns without writing any store-index row for that key. Subsequent
installs therefore can’t warm-prefetch these git-hosted tarballs under --ignore-scripts,
repeatedly re-running the materialize+packlist/prepare-probe work instead of hitting the warm path.
Code

pacquet/crates/package-manager/src/install_package_by_snapshot.rs[R371-384]

+                    // `built` tracks `!ignore_scripts`, in lock-step
+                    // with the key shape `snapshot_cache_key` produces —
+                    // otherwise the prefetch and the write would address
+                    // different slots. Under `--ignore-scripts` the
+                    // git-hosted `prepare` is suppressed too, matching
+                    // pnpm's `ignoreScripts`.
+                    let built = !config.ignore_scripts;
+                    let files_index_file = git_hosted_store_index_key(&package_id, built);
                   let GitFetchOutput { cas_paths, built: _built } = GitHostedTarballFetcher {
                       cas_paths: raw_cas_paths,
                       path: t.path.as_deref(),
                       allow_build: &allow_build_closure,
-                        ignore_scripts: false,
+                        ignore_scripts: config.ignore_scripts,
                       unsafe_perm: config.unsafe_perm,
Evidence
The install dispatcher now (a) selects the git-hosted store-index key based on
!config.ignore_scripts and (b) passes config.ignore_scripts into GitHostedTarballFetcher, so
ignore-scripts installs will use the unbuilt keyspace. CreateVirtualStore::snapshot_cache_key
also derives warm-prefetch keys for git-hosted tarballs using `git_hosted_store_index_key(pkg_id,
!ignore_scripts), meaning warm-prefetch depends on that row existing. But GitHostedTarballFetcher`
explicitly returns early on the ignore-scripts fast-path without writing a final-key row, so the row
needed for warm-prefetch is never created in this mode.

pacquet/crates/package-manager/src/install_package_by_snapshot.rs[360-399]
pacquet/crates/package-manager/src/create_virtual_store.rs[1097-1163]
pacquet/crates/git-fetcher/src/tarball_fetcher.rs[156-198]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Under `--ignore-scripts`, `GitHostedTarballFetcher` can take a fast path (`fast_path_eligible && ignore_scripts`) that returns early without queueing a `PackageFilesIndex` row. Because `CreateVirtualStore::snapshot_cache_key(...)` and the dispatcher now use the `unbuilt` git-hosted store-index key when `ignore_scripts=true`, that missing row prevents warm prefetch and forces repeated cold-path work on re-installs.
### Issue Context
This regression becomes reachable because the PR now propagates `config.ignore_scripts` into the git-hosted tarball fetcher and aligns the read/write key shape on `!ignore_scripts`.
### Fix Focus Areas
- /pacquet/crates/git-fetcher/src/tarball_fetcher.rs[156-223]
- /pacquet/crates/package-manager/src/create_virtual_store.rs[1097-1163]
- /pacquet/crates/package-manager/src/install_package_by_snapshot.rs[360-399]
### Suggested change
In `GitHostedTarballFetcher`’s `fast_path_eligible && self.ignore_scripts` branch, still queue a `PackageFilesIndex` row for `self.files_index_file` (the caller-provided key, which will be the `unbuilt` key when `ignore_scripts=true`). You can synthesize the `files` index from `cas_paths` (similar to the `!should_be_built` fast path) and set `requires_build: Some(should_be_built)`.
This keeps `--ignore-scripts` semantics (no scripts executed, and `built=false` keyspace) while restoring warm-prefetch reuse on subsequent installs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. ignoreScripts not from config ✓ Resolved 🐞 Bug ≡ Correctness
Description
Config.ignore_scripts is added and documented as coming from pnpm-workspace.yaml
(ignoreScripts), but WorkspaceSettings doesn’t define/apply an ignoreScripts field and the env
overlay doesn’t map it either. As a result, setting ignoreScripts: true in workspace yaml (or via
PNPM_CONFIG_IGNORE_SCRIPTS) will be silently ignored.
Code

pacquet/crates/config/src/lib.rs[R1024-1036]

+    /// `ignoreScripts` (`--ignore-scripts`). When `true`, no lifecycle
+    /// scripts run — neither dependency build scripts
+    /// (`preinstall`/`install`/`postinstall`) nor the project's own
+    /// lifecycle scripts. Dependency builds that would otherwise be
+    /// reported as ignored are not collected, so the install does not
+    /// fail with `ERR_PNPM_IGNORED_BUILDS` under `strictDepBuilds`.
+    /// Mirrors pnpm's `ignoreScripts`: the during-install build loop
+    /// skips its allow-build gate entirely when set, leaving
+    /// `ignoredBuilds` empty
+    /// (<https://github.com/pnpm/pnpm/blob/b4f8f47ac2/building/during-install/src/index.ts#L137-L150>).
+    /// Default `false`.
+    pub ignore_scripts: bool,
+
Evidence
Config.ignore_scripts is described as a workspace setting, but the workspace-yaml struct and apply
logic have no corresponding field assignment, and the env overlay similarly lacks any
IGNORE_SCRIPTS mapping; therefore config/env cannot set it.

pacquet/crates/config/src/lib.rs[1024-1036]
pacquet/crates/config/src/workspace_yaml.rs[229-255]
pacquet/crates/config/src/workspace_yaml.rs[824-846]
pacquet/crates/config/src/env_overlay.rs[178-189]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Config.ignore_scripts` is documented as `ignoreScripts` from `pnpm-workspace.yaml`, but the workspace-yaml model (`WorkspaceSettings`) and env overlay don’t include the field, so config/env based enablement does nothing.
## Issue Context
`Config` is not deserialized directly; it is constructed from defaults and then overridden via `WorkspaceSettings::apply_to` and `WorkspaceSettings::from_pnpm_config_env`. Any new config knob needs to be added to those overlay surfaces.
## Fix Focus Areas
- pacquet/crates/config/src/workspace_yaml.rs[70-260]
- pacquet/crates/config/src/workspace_yaml.rs[821-880]
- pacquet/crates/config/src/env_overlay.rs[150-205]
- pacquet/crates/config/src/pnpm_default_parity.rs[105-160]
## What to change
1. Add `pub ignore_scripts: Option<bool>` to `WorkspaceSettings` (serde rename_all camelCase will map it to `ignoreScripts`).
2. In `WorkspaceSettings::apply_to`, apply it:
- `if let Some(v) = self.ignore_scripts { config.ignore_scripts = v; }`
3. In `env_overlay.rs`, add a mapping so `PNPM_CONFIG_IGNORE_SCRIPTS` sets the field.
4. Update any default-parity tests/mappings (e.g. `pnpm_default_parity.rs`) to include the new key if appropriate.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1f3f7d2d-e78b-400b-8d36-9b7e3122a779

📥 Commits

Reviewing files that changed from the base of the PR and between 3347398 and 6492995.

📒 Files selected for processing (6)
  • pacquet/crates/config/src/env_overlay.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/config/src/workspace_yaml/tests.rs
  • pacquet/crates/package-manager/src/create_virtual_store.rs
  • pacquet/crates/package-manager/src/create_virtual_store/tests.rs
  • pacquet/crates/package-manager/src/install_package_by_snapshot.rs

📝 Walkthrough

Walkthrough

Adds ignore_scripts: bool (default false) to Config with support for CLI flag, environment variable, and workspace YAML sources. Threads it through CLI dispatch into BuildModules and both install paths to suppress lifecycle scripts and bypass ERR_PNPM_IGNORED_BUILDS reporting. Updates virtual store cache keys and git package handling to reflect the ignore_scripts state.

Changes

--ignore-scripts feature end-to-end

Layer / File(s) Summary
Config.ignore_scripts field
pacquet/crates/config/src/lib.rs
Adds pub ignore_scripts: bool (default false) to Config with documentation covering its effect on lifecycle scripts and strictDepBuilds reporting.
Config.ignore_scripts from environment and workspace.yaml
pacquet/crates/config/src/workspace_yaml.rs, pacquet/crates/config/src/env_overlay.rs, pacquet/crates/config/src/workspace_yaml/tests.rs
Adds ignore_scripts: Option<bool> to WorkspaceSettings parsed from pnpm-workspace.yaml camelCase ignoreScripts, applies it to Config via apply_to, and wires IGNORE_SCRIPTS environment variable support into from_pnpm_config_env. Includes test verifying YAML parsing and config propagation.
CLI flag definition and dispatch wiring
pacquet/crates/cli/src/cli_args/install.rs, pacquet/crates/cli/src/cli_args.rs
Adds --ignore-scripts boolean field to InstallArgs (ignored in InstallArgs::run in favor of config-driven value) and wires it as an enable-only override into cfg.ignore_scripts during CLI dispatch.
BuildModules ignore_scripts gating logic
pacquet/crates/package-manager/src/build_modules.rs
Adds ignore_scripts: bool to BuildModules, threads it into build_one_snapshot, and changes the gate to should_run_scripts = requires_build && !ignore_scripts, bypassing allow-build policy checks and ignored-builds collection while still applying patches.
Install path wiring
pacquet/crates/package-manager/src/install.rs, pacquet/crates/package-manager/src/install_frozen_lockfile.rs
Guards project lifecycle scripts in install.rs with !config.ignore_scripts and passes config.ignore_scripts into BuildModules in install_frozen_lockfile.rs.
Virtual store cache keys respect ignore_scripts
pacquet/crates/package-manager/src/create_virtual_store.rs
Updates snapshot_cache_key to accept ignore_scripts: bool and changes git-related arms to use built = !ignore_scripts instead of hardcoded true. Both warm-batch call sites pass config.ignore_scripts to align cache keys with store-index dispatch behavior.
Git package install built flag and ignore_scripts parameter
pacquet/crates/package-manager/src/install_package_by_snapshot.rs
Updates git-sourced package handling (gitHosted: true tarball and plain git resolution) to compute built as !config.ignore_scripts and pass config.ignore_scripts to fetchers instead of hardcoded values, aligning store-index keys with script-preparation behavior.
Unit and integration tests
pacquet/crates/package-manager/src/build_modules/tests.rs, pacquet/crates/package-manager/src/create_virtual_store/tests.rs, pacquet/crates/cli/tests/lifecycle_scripts.rs, pacquet/crates/package-manager/src/install_package_from_registry/tests.rs
New unit test verifies ignored-builds list is empty under ignore_scripts: true; all existing BuildModules tests gain ignore_scripts: false; create_virtual_store unit tests updated for new snapshot_cache_key signature; new CLI integration tests verify dep-build and project lifecycle suppression; registry test fixture gains explicit ignore_scripts: false.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • pnpm/pnpm#12051: Introduced the project/workspace lifecycle script execution in install.rs that this PR now gates behind !config.ignore_scripts.

Suggested labels

area: cli/dlx, area: config dependencies

🐇 A flag was born, --ignore-scripts its name,
Lifecycle hooks skipped, no build phase to claim.
The ignored-builds list stays empty and clear,
Cache keys aligned, no conflicts to fear!
Config set, tests pass—the feature hops with cheer! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 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 an --ignore-scripts flag to the install command, which is the primary feature of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 feat/pacquet-ignore-scripts

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 and usage tips.

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add --ignore-scripts to pacquet install (pnpm-compatible behavior)
✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

Walkthroughs

Description
• Add pacquet install --ignore-scripts to suppress dependency and project lifecycle scripts.
• Bypass ignored-build collection so strictDepBuilds won’t raise ERR_PNPM_IGNORED_BUILDS.
• Add unit + CLI tests covering ignored-build behavior and lifecycle script suppression.
Diagram
graph TD
  A["pacquet CLI"] --> B["InstallArgs (--ignore-scripts)"] --> C["CLI dispatch merge"] --> D[("Config.ignore_scripts")] --> E["Install pipeline"] --> F["BuildModules (build loop)"] --> H["ignoredBuilds set"]
  D --> G["Project lifecycle scripts"]
  F --> G
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Map --ignore-scripts to strictDepBuilds=false
  • ➕ Smallest behavioral change; avoids ERR_PNPM_IGNORED_BUILDS by design
  • ➖ Not pnpm-compatible: still runs scripts unless separately gated
  • ➖ Changes semantics beyond scripts (strictness affects reporting/behavior)
  • ➖ Doesn’t address project lifecycle scripts consistently
2. Skip scripts but still populate ignoredBuilds (don’t fail)
  • ➕ Preserves visibility into what would have been ignored
  • ➕ Keeps telemetry/warnings possible even under ignore-scripts
  • ➖ Diverges from pnpm semantics (pnpm leaves ignoredBuilds empty under ignoreScripts)
  • ➖ Risk of downstream code still treating ignoredBuilds as actionable and failing/printing unexpectedly

Recommendation: Keep the PR’s current approach: treat --ignore-scripts as a top-level bypass that prevents scripts from running and prevents adding entries to ignoredBuilds, matching pnpm’s ignoreScripts semantics. This yields predictable compatibility (including benchmarks) and avoids accidental strict-mode failures.

Grey Divider

File Changes

Enhancement (6)
cli_args.rs Merge --ignore-scripts into config as enable-only flag +3/-0

Merge --ignore-scripts into config as enable-only flag

• Extends the install dispatch merge logic to OR 'args.ignore_scripts' into 'cfg.ignore_scripts', ensuring the CLI flag can only enable the behavior and won’t override a YAML 'true' back to false. Mirrors the pattern used for other enable-only flags (e.g., '--frozen-store').

pacquet/crates/cli/src/cli_args.rs


install.rs Add --ignore-scripts flag to install CLI args +16/-0

Add --ignore-scripts flag to install CLI args

• Introduces the '--ignore-scripts' install flag with documentation explaining pnpm parity and strictDepBuilds implications. Ensures the install implementation reads the effective value from 'config.ignore_scripts' (post-dispatch merge) rather than directly from the args struct.

pacquet/crates/cli/src/cli_args/install.rs


lib.rs Add Config.ignore_scripts with pnpm-compatible semantics +13/-0

Add Config.ignore_scripts with pnpm-compatible semantics

• Adds a new 'Config.ignore_scripts' field with docs describing that all lifecycle scripts are suppressed and ignored builds are not collected, preventing strictDepBuilds failures. Documents intended parity with pnpm’s 'ignoreScripts' behavior and default value.

pacquet/crates/config/src/lib.rs


build_modules.rs Thread ignore_scripts into build loop to bypass allow-build gate +23/-2

Thread ignore_scripts into build loop to bypass allow-build gate

• Adds 'ignore_scripts' to 'BuildModules' and threads it into 'build_one_snapshot'. Updates the build decision to skip running scripts entirely when 'ignore_scripts' is true, which also avoids adding packages to the ignored-builds set while still allowing patches to apply.

pacquet/crates/package-manager/src/build_modules.rs


install.rs Skip project lifecycle scripts when ignore_scripts is enabled +5/-1

Skip project lifecycle scripts when ignore_scripts is enabled

• Gates project lifecycle script execution on '!config.ignore_scripts' in addition to full-install checks. Aligns project-script behavior with pnpm, where ignoreScripts suppresses both dependency and project lifecycle hooks.

pacquet/crates/package-manager/src/install.rs


install_frozen_lockfile.rs Pass ignore_scripts into frozen-lockfile build phase +1/-0

Pass ignore_scripts into frozen-lockfile build phase

• Wires 'config.ignore_scripts' into the 'BuildModules' invocation used during the frozen-lockfile install path so the build phase respects '--ignore-scripts' consistently.

pacquet/crates/package-manager/src/install_frozen_lockfile.rs


Tests (3)
lifecycle_scripts.rs Add CLI tests for --ignore-scripts behavior +72/-0

Add CLI tests for --ignore-scripts behavior

• Adds a strictDepBuilds regression test asserting 'pacquet install --ignore-scripts' exits 0 without emitting 'ERR_PNPM_IGNORED_BUILDS' and that dependency scripts do not generate artifacts. Adds a project-level lifecycle test verifying project scripts are also suppressed under '--ignore-scripts'.

pacquet/crates/cli/tests/lifecycle_scripts.rs


tests.rs Add unit test ensuring ignore_scripts returns empty ignored-builds set +77/-0

Add unit test ensuring ignore_scripts returns empty ignored-builds set

• Updates existing BuildModules test fixtures to include 'ignore_scripts: false'. Adds a new unit test asserting that with default-deny allowBuilds, enabling 'ignore_scripts' silently skips builds and returns an empty ignored-builds set.

pacquet/crates/package-manager/src/build_modules/tests.rs


tests.rs Update registry-install test config to include ignore_scripts +1/-0

Update registry-install test config to include ignore_scripts

• Extends the test config builder to initialize 'ignore_scripts: false', keeping struct construction consistent after adding the new config field.

pacquet/crates/package-manager/src/install_package_from_registry/tests.rs


Grey Divider

Qodo Logo

Comment thread pacquet/crates/cli/src/cli_args/install.rs
Comment thread pacquet/crates/config/src/lib.rs
…ml/env

Two follow-ups from PR review:

- Git and git-hosted-tarball dependencies were fetched with
  `ignore_scripts: false` hardcoded, so their `prepare` script still ran
  during install even under `--ignore-scripts`. Thread
  `config.ignore_scripts` into `GitFetcher` / `GitHostedTarballFetcher`,
  and flip the git store-index key's `built` dimension to
  `!ignore_scripts` at both the write site (`install_package_by_snapshot`)
  and the warm-prefetch site (`snapshot_cache_key`) so the two stay in
  lock-step and address the same slot.

- `Config.ignore_scripts` was only set by the CLI flag; `ignoreScripts`
  in `pnpm-workspace.yaml` and `PNPM_CONFIG_IGNORE_SCRIPTS` were silently
  dropped. Wire it through `WorkspaceSettings` + `apply_to` and the env
  overlay, mirroring `strictDepBuilds`.
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 16, 2026

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 6492995

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.92308% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.02%. Comparing base (3d1fd20) to head (6492995).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
...package-manager/src/install_package_by_snapshot.rs 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12454      +/-   ##
==========================================
+ Coverage   88.00%   88.02%   +0.02%     
==========================================
  Files         308      308              
  Lines       41418    41438      +20     
==========================================
+ Hits        36448    36476      +28     
+ Misses       4970     4962       -8     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown
Contributor

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.00      8.1±0.15ms   537.6 KB/sec    1.03      8.3±0.28ms   523.0 KB/sec

@github-actions

Copy link
Copy Markdown
Contributor

Integrated-Benchmark Report (Linux)

Each scenario reports direct installs and pnpr installs. Bencher consumes pacquet@HEAD and pnpr@HEAD.

Scenario: Isolated linker: fresh restore, cold cache + cold store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 4.276 ± 0.123 4.140 4.435 1.98 ± 0.18
pacquet@main 4.268 ± 0.141 4.072 4.540 1.98 ± 0.18
pnpr@HEAD 2.155 ± 0.180 1.967 2.417 1.00
pnpr@main 2.216 ± 0.174 1.968 2.520 1.03 ± 0.12
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 4.275508483960001,
      "stddev": 0.1230199108876675,
      "median": 4.21764453516,
      "user": 4.115974999999999,
      "system": 3.462112559999999,
      "min": 4.14023865566,
      "max": 4.434791377660001,
      "times": [
        4.41957900666,
        4.434791377660001,
        4.42864382566,
        4.17676131666,
        4.373981742660001,
        4.22096236566,
        4.19641441166,
        4.149385432660001,
        4.14023865566,
        4.21432670466
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 4.267578029160001,
      "stddev": 0.14142806817970627,
      "median": 4.22265395216,
      "user": 4.1522542,
      "system": 3.4567897599999995,
      "min": 4.071509386660001,
      "max": 4.53964311066,
      "times": [
        4.249514550660001,
        4.1928406786600005,
        4.3108781376600005,
        4.17748889966,
        4.47812487966,
        4.53964311066,
        4.071509386660001,
        4.2104727436600005,
        4.226155261660001,
        4.21915264266
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.15525635456,
      "stddev": 0.17994723233776005,
      "median": 2.14009635816,
      "user": 2.7678242,
      "system": 2.92332506,
      "min": 1.9671724476599999,
      "max": 2.41680236466,
      "times": [
        2.04264973366,
        2.41680236466,
        2.29963967466,
        1.9898454866600002,
        2.38391106966,
        1.99337845166,
        2.24783306566,
        2.23754298266,
        1.9671724476599999,
        1.97378826866
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.21553293906,
      "stddev": 0.17435404924226766,
      "median": 2.20404064166,
      "user": 2.7580451999999993,
      "system": 2.8880944599999996,
      "min": 1.96766880866,
      "max": 2.51973967066,
      "times": [
        2.05140431166,
        2.51973967066,
        2.27691976766,
        2.05345286266,
        1.96766880866,
        2.38660655066,
        2.3666689496599997,
        2.17216639166,
        2.12478718566,
        2.23591489166
      ]
    }
  ]
}

Scenario: Isolated linker: fresh restore, hot cache + hot store

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 641.5 ± 10.1 629.3 661.0 1.00
pacquet@main 645.3 ± 16.9 628.1 680.4 1.01 ± 0.03
pnpr@HEAD 734.6 ± 139.3 666.8 1128.2 1.15 ± 0.22
pnpr@main 717.3 ± 31.8 682.1 780.7 1.12 ± 0.05
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.6415175972,
      "stddev": 0.010063001061014923,
      "median": 0.6385365362,
      "user": 0.38652053999999997,
      "system": 1.32276192,
      "min": 0.6293475152,
      "max": 0.6610397842,
      "times": [
        0.6441062362,
        0.6535153872,
        0.6475681032,
        0.6359760822,
        0.6293475152,
        0.6410969902,
        0.6610397842,
        0.6347141472,
        0.6348659082,
        0.6329458182
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.6453401181,
      "stddev": 0.016878981217364634,
      "median": 0.6402136897,
      "user": 0.38593734,
      "system": 1.33173902,
      "min": 0.6280682282,
      "max": 0.6803743252,
      "times": [
        0.6409134882,
        0.6395138912,
        0.6303170112,
        0.6313699042,
        0.6325878912,
        0.6545337752,
        0.6565804452,
        0.6591422212,
        0.6280682282,
        0.6803743252
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.7345697271,
      "stddev": 0.13931752126104033,
      "median": 0.6903775687,
      "user": 0.41026444,
      "system": 1.37049642,
      "min": 0.6667543992,
      "max": 1.1282069932,
      "times": [
        0.6822880862,
        0.6829673032,
        0.6932226762,
        0.6963793512,
        0.6667543992,
        0.6875324612,
        0.6978832452,
        0.6798248212,
        1.1282069932,
        0.7306379342
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.717258234,
      "stddev": 0.03184041178818746,
      "median": 0.7051701212,
      "user": 0.40856773999999996,
      "system": 1.3671607199999998,
      "min": 0.6821498672,
      "max": 0.7807257762,
      "times": [
        0.6962543652000001,
        0.6999884452,
        0.6952948782,
        0.7501419692,
        0.7458155172,
        0.7103517972,
        0.6910880022,
        0.7807257762,
        0.6821498672,
        0.7207717222
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, cold cache + cold store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 4.317 ± 0.051 4.237 4.380 2.06 ± 0.08
pacquet@main 4.309 ± 0.038 4.218 4.359 2.06 ± 0.08
pnpr@HEAD 2.096 ± 0.078 1.993 2.241 1.00
pnpr@main 2.214 ± 0.134 2.077 2.403 1.06 ± 0.07
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 4.31664539684,
      "stddev": 0.050791197054236854,
      "median": 4.33301975444,
      "user": 3.9284382400000006,
      "system": 3.3135919399999993,
      "min": 4.23699236394,
      "max": 4.3799210109399995,
      "times": [
        4.36839560494,
        4.249150247939999,
        4.35821845294,
        4.23699236394,
        4.33939741994,
        4.2847114589399995,
        4.3799210109399995,
        4.27821664394,
        4.3448086759399995,
        4.32664208894
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 4.308814524640001,
      "stddev": 0.037804329570098966,
      "median": 4.31587117944,
      "user": 3.903358339999999,
      "system": 3.32354734,
      "min": 4.21758701694,
      "max": 4.359113454939999,
      "times": [
        4.30284782694,
        4.32276689494,
        4.3295025869399995,
        4.3308856129399995,
        4.3000241379399995,
        4.28838850794,
        4.21758701694,
        4.32805374294,
        4.3089754639399995,
        4.359113454939999
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.09647864424,
      "stddev": 0.07790815723253594,
      "median": 2.08161855994,
      "user": 2.5836913399999997,
      "system": 2.8480049399999996,
      "min": 1.99311409694,
      "max": 2.2407476549400003,
      "times": [
        2.13139757694,
        2.03977451494,
        2.19674750194,
        2.10168181494,
        2.03623701694,
        2.2407476549400003,
        1.99311409694,
        2.06155530494,
        2.04094822294,
        2.12258273694
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.2137885182400003,
      "stddev": 0.13368543298988975,
      "median": 2.1660770029400003,
      "user": 2.55339854,
      "system": 2.8187710399999997,
      "min": 2.07716663794,
      "max": 2.40300392794,
      "times": [
        2.1999586259400004,
        2.13219537994,
        2.39849690194,
        2.0918490759400004,
        2.08319626494,
        2.07716663794,
        2.40300392794,
        2.29471546094,
        2.34375511194,
        2.11354779494
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, hot cache + hot store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 1.365 ± 0.019 1.337 1.395 2.08 ± 0.20
pacquet@main 1.399 ± 0.078 1.354 1.618 2.13 ± 0.24
pnpr@HEAD 0.674 ± 0.075 0.639 0.885 1.03 ± 0.15
pnpr@main 0.657 ± 0.064 0.627 0.836 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 1.3653209774799997,
      "stddev": 0.0194264523945747,
      "median": 1.36475800058,
      "user": 1.36054204,
      "system": 1.7205275,
      "min": 1.33743613258,
      "max": 1.39488686158,
      "times": [
        1.33743613258,
        1.36844188258,
        1.39488686158,
        1.34398594758,
        1.36107411858,
        1.36884182058,
        1.3858272465800001,
        1.35730788858,
        1.34829584658,
        1.38711202958
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 1.39860041178,
      "stddev": 0.0784553440720034,
      "median": 1.37182499358,
      "user": 1.36625634,
      "system": 1.7214803999999997,
      "min": 1.35435639858,
      "max": 1.61776389858,
      "times": [
        1.38470266058,
        1.36354833458,
        1.61776389858,
        1.35925887858,
        1.40413008158,
        1.38987315958,
        1.3687207185799999,
        1.37039909958,
        1.37325088758,
        1.35435639858
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.6737814226800001,
      "stddev": 0.07464027302602376,
      "median": 0.6503516785800001,
      "user": 0.34524124,
      "system": 1.2842459,
      "min": 0.63920595758,
      "max": 0.88479235758,
      "times": [
        0.66522667258,
        0.88479235758,
        0.63920595758,
        0.65455581758,
        0.64614753958,
        0.64586458858,
        0.65813283558,
        0.65884957158,
        0.64015239558,
        0.64488649058
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.65651984208,
      "stddev": 0.06354666510017888,
      "median": 0.63827621408,
      "user": 0.32342284,
      "system": 1.2623119,
      "min": 0.62739880758,
      "max": 0.83626038058,
      "times": [
        0.64877699758,
        0.64400263258,
        0.63875552558,
        0.63239486558,
        0.62869434458,
        0.63779690258,
        0.62739880758,
        0.64152439458,
        0.62959356958,
        0.83626038058
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, cold cache + hot store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 3.050 ± 0.032 3.017 3.120 4.68 ± 0.10
pacquet@main 3.045 ± 0.053 2.995 3.185 4.68 ± 0.12
pnpr@HEAD 0.673 ± 0.005 0.664 0.681 1.03 ± 0.02
pnpr@main 0.651 ± 0.011 0.641 0.680 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 3.0498671831599995,
      "stddev": 0.03245688046387863,
      "median": 3.03724979336,
      "user": 1.8202639600000001,
      "system": 1.99378454,
      "min": 3.01679084986,
      "max": 3.12026201086,
      "times": [
        3.01679084986,
        3.03246192586,
        3.03938827486,
        3.05885268286,
        3.03291216586,
        3.0351113118599997,
        3.01897856186,
        3.08781323886,
        3.12026201086,
        3.0561008088599997
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 3.044791149359999,
      "stddev": 0.05271179283550148,
      "median": 3.03016258886,
      "user": 1.7930486599999997,
      "system": 1.9946519399999996,
      "min": 2.99489201686,
      "max": 3.18464182586,
      "times": [
        3.04837074586,
        3.0434623088599997,
        3.06143880786,
        3.0178092678599997,
        3.01093336986,
        3.03270193686,
        3.02762324086,
        2.99489201686,
        3.18464182586,
        3.0260379728599998
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.67289773096,
      "stddev": 0.005157847565035208,
      "median": 0.67222233436,
      "user": 0.34157236,
      "system": 1.3202358399999998,
      "min": 0.66439858986,
      "max": 0.68067315786,
      "times": [
        0.6707948678600001,
        0.67104295786,
        0.67894453286,
        0.67695802486,
        0.67298184486,
        0.68067315786,
        0.66439858986,
        0.6666497208600001,
        0.67146282386,
        0.67507078886
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.65119836216,
      "stddev": 0.011422481451060083,
      "median": 0.6481394943600001,
      "user": 0.32768586,
      "system": 1.27764444,
      "min": 0.64142531386,
      "max": 0.67974423786,
      "times": [
        0.6487526288600001,
        0.64251562486,
        0.6461604338600001,
        0.6475263598600001,
        0.6540188448600001,
        0.6593308268600001,
        0.67974423786,
        0.6430398498600001,
        0.6494695008600001,
        0.64142531386
      ]
    }
  ]
}

@github-actions

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12454
Testbedpacquet
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
milliseconds (ms)
(Result Δ%)
Upper Boundary
milliseconds (ms)
(Limit %)
isolated-linker.fresh-install.cold-cache.cold-store📈 view plot
🚷 view threshold
4,316.65 ms
(+3.51%)Baseline: 4,170.37 ms
5,004.44 ms
(86.26%)
isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
🚷 view threshold
3,049.87 ms
(+2.05%)Baseline: 2,988.48 ms
3,586.17 ms
(85.05%)
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
🚷 view threshold
1,365.32 ms
(+3.98%)Baseline: 1,313.00 ms
1,575.60 ms
(86.65%)
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
🚷 view threshold
4,275.51 ms
(+8.25%)Baseline: 3,949.75 ms
4,739.70 ms
(90.21%)
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
🚷 view threshold
641.52 ms
(+3.34%)Baseline: 620.80 ms
744.97 ms
(86.11%)
🐰 View full continuous benchmarking report in Bencher

@github-actions

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12454
Testbedpnpr

⚠️ WARNING: No Threshold found!

Without a Threshold, no Alerts will ever be generated.

Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the --ci-only-thresholds flag.

Click to view all benchmark results
BenchmarkLatencymilliseconds (ms)
isolated-linker.fresh-install.cold-cache.cold-store📈 view plot
⚠️ NO THRESHOLD
2,096.48 ms
isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
672.90 ms
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
673.78 ms
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
⚠️ NO THRESHOLD
2,155.26 ms
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
734.57 ms
🐰 View full continuous benchmarking report in Bencher

@zkochan zkochan merged commit 7cd5594 into main Jun 16, 2026
30 checks passed
@zkochan zkochan deleted the feat/pacquet-ignore-scripts branch June 16, 2026 17:12
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