From 2b476f01e09b13f64108f1268ad3975a93a73315 Mon Sep 17 00:00:00 2001 From: Liang Date: Thu, 24 Sep 2026 22:37:56 +0800 Subject: [PATCH 1/9] feat(cli): support --ignore-scripts=false for global packages --- .../snapshots/cli_helper_message.md | 5 +- .../snapshots/command_add_bun.md | 2 +- .../snapshots/command_add_npm10.md | 2 +- .../snapshots/command_add_npm11.md | 2 +- .../snapshots/command_add_pnpm10.global.md | 2 +- .../snapshots/command_add_pnpm10.local.md | 2 +- .../snapshots/command_add_pnpm11.md | 2 +- .../snapshots/command_add_pnpm12.md | 2 +- .../snapshots/command_add_pnpm9.md | 2 +- .../snapshots/command_add_yarn4.md | 2 +- .../snapshots/command_update_bun.md | 1 + .../snapshots/command_update_pnpm10.global.md | 1 + .../snapshots/command_update_pnpm10.local.md | 1 + .../snapshots/command_update_pnpm11.md | 1 + .../global_install_scripts/.node-version | 1 + .../global_install_scripts/mock-manifest.json | 60 +++++++++ .../global_install_scripts/my-cli/check.cjs | 13 ++ .../my-cli/package.json | 13 ++ .../native-addon/package.json | 7 + .../global_install_scripts/package.json | 5 + .../global_install_scripts/setup-npm.cjs | 11 ++ .../global_install_scripts/snapshots.toml | 45 +++++++ .../global_scripts_default_and_enable.md | 123 ++++++++++++++++++ .../snapshots/global_scripts_npm12.md | 56 ++++++++ .../install_ignore_scripts/snapshots.toml | 6 +- .../global_install_ignore_scripts.md | 16 ++- .../snapshots/npm_install_with_options.md | 2 +- .../npm_update_notifier/snapshots.toml | 2 +- .../snapshots/npm_global_update_notifier.md | 2 +- .../snapshots/yarn_install_with_options.md | 2 +- crates/vp_global_cli/src/cli.rs | 5 +- .../src/commands/global/install.rs | 122 ++++++++++++++++- crates/vp_pm_cli/src/cli.rs | 6 +- .../vp_pm_cli/src/resolution/commands/add.rs | 13 +- .../src/resolution/commands/install.rs | 13 +- .../src/resolution/commands/update.rs | 4 + docs/guide/install.md | 12 ++ 37 files changed, 537 insertions(+), 29 deletions(-) create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/.node-version create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/mock-manifest.json create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/my-cli/check.cjs create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/my-cli/package.json create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/native-addon/package.json create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/package.json create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/setup-npm.cjs create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_default_and_enable.md create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_npm12.md diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md index aa0b6e0fe5..919fafb986 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md @@ -115,7 +115,7 @@ Options: --prefer-offline Use cached packages when available --offline Only use packages already in cache -f, --force Force reinstall all dependencies - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) @@ -159,7 +159,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -228,6 +228,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages + --ignore-scripts[=] Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md index 65acc370c9..cbdfde2bb2 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md index fa89053e35..5f375fc77c 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md index 6994f3ef11..628c217a94 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md index 1d8c2acc5d..5d93bf4a0c 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md index 2c76ae81bf..905ff86eb7 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md @@ -30,7 +30,7 @@ Options: Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md index f605e1480e..394142b5d4 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md index c1c4688e28..2ddb82486d 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md index 597153f2f6..d1dfac9ed5 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md index 6e70fbed1c..3f090f5a19 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md index 41f16db801..09efa01152 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md @@ -18,6 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages + --ignore-scripts[=] Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md index ffc46aac1c..91cf7cc870 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md @@ -18,6 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages + --ignore-scripts[=] Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md index ea57f581d1..6af09259e1 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md @@ -16,6 +16,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages + --ignore-scripts[=] Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md index af2231ad83..9eeead6a59 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md @@ -18,6 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages + --ignore-scripts[=] Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/.node-version b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/.node-version new file mode 100644 index 0000000000..c94711948a --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/.node-version @@ -0,0 +1 @@ +22.23.2 diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/mock-manifest.json b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/mock-manifest.json new file mode 100644 index 0000000000..918973bce2 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/mock-manifest.json @@ -0,0 +1,60 @@ +{ + "my-cli": { + "name": "my-cli", + "dist-tags": { + "latest": "2.0.0" + }, + "versions": { + "1.0.0": { + "name": "my-cli", + "version": "1.0.0", + "bin": { + "my-cli": "check.cjs" + }, + "scripts": { + "postinstall": "node -e \"require('node:fs').writeFileSync('postinstall-ran', process.version)\"" + }, + "dependencies": { + "native-addon": "1.0.0" + }, + "dist": { + "tarball": "{REGISTRY}/my-cli/-/my-cli-1.0.0.tgz" + } + }, + "2.0.0": { + "name": "my-cli", + "version": "2.0.0", + "bin": { + "my-cli": "check.cjs" + }, + "scripts": { + "postinstall": "node -e \"require('node:fs').writeFileSync('postinstall-ran', process.version)\"" + }, + "dependencies": { + "native-addon": "1.0.0" + }, + "dist": { + "tarball": "{REGISTRY}/my-cli/-/my-cli-2.0.0.tgz" + } + } + } + }, + "native-addon": { + "name": "native-addon", + "dist-tags": { + "latest": "1.0.0" + }, + "versions": { + "1.0.0": { + "name": "native-addon", + "version": "1.0.0", + "scripts": { + "postinstall": "node -e \"require('node:fs').writeFileSync('postinstall-ran', process.version)\"" + }, + "dist": { + "tarball": "{REGISTRY}/native-addon/-/native-addon-1.0.0.tgz" + } + } + } + } +} diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/my-cli/check.cjs b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/my-cli/check.cjs new file mode 100644 index 0000000000..e49596584b --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/my-cli/check.cjs @@ -0,0 +1,13 @@ +#!/usr/bin/env node +const assert = require('node:assert/strict'); +const { existsSync, readFileSync } = require('node:fs'); +const { dirname, join } = require('node:path'); + +// Exercise the installed CLI, including a transitive package's build output. +const parent = existsSync(join(__dirname, 'postinstall-ran')) ? 'ran' : 'skipped'; +const child = existsSync(join(dirname(require.resolve('native-addon/package.json')), 'postinstall-ran')) ? 'ran' : 'skipped'; +assert.equal(parent, process.argv[2]); +assert.equal(child, process.argv[3]); +if (parent === 'ran') assert.equal(readFileSync(join(__dirname, 'postinstall-ran'), 'utf8'), process.version); +if (child === 'ran') assert.equal(readFileSync(join(dirname(require.resolve('native-addon/package.json')), 'postinstall-ran'), 'utf8'), process.version); +console.log(`my-cli: ${parent}; native-addon: ${child}`); diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/my-cli/package.json b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/my-cli/package.json new file mode 100644 index 0000000000..35d1965a9d --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/my-cli/package.json @@ -0,0 +1,13 @@ +{ + "name": "my-cli", + "version": "1.0.0", + "bin": { + "my-cli": "check.cjs" + }, + "scripts": { + "postinstall": "node -e \"require('node:fs').writeFileSync('postinstall-ran', process.version)\"" + }, + "dependencies": { + "native-addon": "1.0.0" + } +} diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/native-addon/package.json b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/native-addon/package.json new file mode 100644 index 0000000000..6b56aeb8ef --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/native-addon/package.json @@ -0,0 +1,7 @@ +{ + "name": "native-addon", + "version": "1.0.0", + "scripts": { + "postinstall": "node -e \"require('node:fs').writeFileSync('postinstall-ran', process.version)\"" + } +} diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/package.json b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/package.json new file mode 100644 index 0000000000..2036978713 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/package.json @@ -0,0 +1,5 @@ +{ + "name": "global-install-scripts", + "private": true, + "packageManager": "npm@12.0.2" +} diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/setup-npm.cjs b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/setup-npm.cjs new file mode 100644 index 0000000000..e3a77d3298 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/setup-npm.cjs @@ -0,0 +1,11 @@ +const assert = require('node:assert/strict'); +const { spawnSync } = require('node:child_process'); +const { dirname, join, relative } = require('node:path'); + +// Replace npm only inside this unseeded case's runtime, using the same Node.js. +const prefix = process.platform === 'win32' ? dirname(process.execPath) : dirname(dirname(process.execPath)); +assert.ok(!relative(process.env.VP_HOME, prefix).startsWith('..')); +const npm = join(prefix, process.platform === 'win32' ? 'node_modules/npm' : 'lib/node_modules/npm'); +const result = spawnSync(process.execPath, [join(npm, 'bin/npm-cli.js'), 'install', '-g', 'npm@12.0.2', '--prefix', prefix, '--ignore-scripts'], { stdio: 'inherit' }); +assert.equal(result.status, 0); +assert.equal(require(join(npm, 'package.json')).version, '12.0.2'); diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml new file mode 100644 index 0000000000..3ab7d01219 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml @@ -0,0 +1,45 @@ +[[case]] +name = "global_scripts_default_and_enable" +vp = "global" +local-registry = true +comment = "Global installs and updates skip direct and transitive scripts by default and warn last. Explicit false runs all scripts with the selected Node.js, including Node 20." +env = { npm_config_ignore_scripts = "false", npm_config_dangerously_allow_all_scripts = "true", npm_config_audit = "false", npm_config_fund = "false" } +steps = [ + { argv = ["vpt", "mkdir", "-p", "tarballs"], snapshot = false }, + { argv = ["npm", "pack", "./native-addon", "--ignore-scripts", "--pack-destination", "tarballs"], snapshot = false }, + { argv = ["npm", "pack", "./my-cli", "--ignore-scripts", "--pack-destination", "tarballs"], snapshot = false }, + { argv = ["vpt", "json-edit", "my-cli/package.json", "version", "2.0.0"], snapshot = false }, + { argv = ["npm", "pack", "./my-cli", "--ignore-scripts", "--pack-destination", "tarballs"], snapshot = false }, + ["vp", "install", "-g", "my-cli@1.0.0", "native-addon@1.0.0"], + ["my-cli", "skipped", "skipped"], + { argv = ["vp", "install", "-g", "my-cli@1.0.0", "--ignore-scripts=false"], envs = [["npm_config_ignore_scripts", "true"], ["npm_config_dangerously_allow_all_scripts", "false"]] }, + ["my-cli", "ran", "ran"], + { argv = ["vp", "env", "install", "node@20.19.6"], snapshot = false }, + ["vp", "add", "-g", "my-cli@1.0.0", "--node", "20.19.6", "--ignore-scripts"], + ["my-cli", "skipped", "skipped"], + ["vp", "add", "-g", "my-cli@1.0.0", "--node", "20.19.6", "--ignore-scripts=false"], + ["my-cli", "ran", "ran"], + ["vp", "update", "-g", "my-cli@2.0.0"], + ["my-cli", "skipped", "skipped"], + ["vp", "update", "-g", "my-cli@1.0.0", "--ignore-scripts=false"], + ["my-cli", "ran", "ran"], +] + +[[case]] +name = "global_scripts_npm12" +vp = "global" +seed-runtime = false +local-registry = true +comment = "A case-owned Node runtime with bundled npm 12 still runs all scripts only when explicitly enabled, without changing Node.js." +env = { npm_config_ignore_scripts = "true", npm_config_dangerously_allow_all_scripts = "false", npm_config_audit = "false", npm_config_fund = "false" } +steps = [ + { argv = ["node", "setup-npm.cjs"], snapshot = false, timeout = 120000 }, + ["node", "-p", "require(require('node:path').join(require('node:path').dirname(process.execPath), process.platform === 'win32' ? 'node_modules/npm/package.json' : '../lib/node_modules/npm/package.json')).version"], + { argv = ["vpt", "mkdir", "-p", "tarballs"], snapshot = false }, + { argv = ["npm", "pack", "./native-addon", "--ignore-scripts", "--pack-destination", "tarballs"], snapshot = false }, + { argv = ["npm", "pack", "./my-cli", "--ignore-scripts", "--pack-destination", "tarballs"], snapshot = false }, + ["vp", "install", "-g", "my-cli@1.0.0"], + ["my-cli", "skipped", "skipped"], + ["vp", "install", "-g", "my-cli@1.0.0", "--ignore-scripts=false"], + ["my-cli", "ran", "ran"], +] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_default_and_enable.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_default_and_enable.md new file mode 100644 index 0000000000..f1562c7ab7 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_default_and_enable.md @@ -0,0 +1,123 @@ +# global_scripts_default_and_enable + +Global installs and updates skip direct and transitive scripts by default and warn last. Explicit false runs all scripts with the selected Node.js, including Node 20. + +## `vpt mkdir -p tarballs` + + +## `npm pack ./native-addon --ignore-scripts --pack-destination tarballs` + + +## `npm pack ./my-cli --ignore-scripts --pack-destination tarballs` + + +## `vpt json-edit my-cli/package.json version 2.0.0` + + +## `npm pack ./my-cli --ignore-scripts --pack-destination tarballs` + + +## `vp install -g my-cli@1.0.0 native-addon@1.0.0` + +``` +VITE+ - The Unified Toolchain for the Web + +info: Installing 2 global packages with Node.js +✓ Installed my-cli 1.0.0 + Bins: my-cli + +✓ Installed native-addon 1.0.0 +warning: Lifecycle scripts were skipped for: my-cli, native-addon. +To allow them, reinstall with: + vp install -g my-cli@1.0.0 --ignore-scripts=false +warning: Lifecycle scripts were skipped for: native-addon. +To allow them, reinstall with: + vp install -g native-addon@1.0.0 --ignore-scripts=false +``` + +## `my-cli skipped skipped` + +``` +my-cli: skipped; native-addon: skipped +``` + +## `npm_config_ignore_scripts=true npm_config_dangerously_allow_all_scripts=false vp install -g my-cli@1.0.0 --ignore-scripts=false` + +``` +VITE+ - The Unified Toolchain for the Web + +info: Installing 1 global package with Node.js +✓ Installed my-cli 1.0.0 + Bins: my-cli +``` + +## `my-cli ran ran` + +``` +my-cli: ran; native-addon: ran +``` + +## `vp env install node@20.19.6` + + +## `vp add -g my-cli@1.0.0 --node 20.19.6 --ignore-scripts` + +``` +info: Installing 1 global package with Node.js +✓ Installed my-cli 1.0.0 + Bins: my-cli +warning: Lifecycle scripts were skipped for: my-cli, native-addon. +To allow them, reinstall with: + vp install -g my-cli@1.0.0 --node --ignore-scripts=false +``` + +## `my-cli skipped skipped` + +``` +my-cli: skipped; native-addon: skipped +``` + +## `vp add -g my-cli@1.0.0 --node 20.19.6 --ignore-scripts=false` + +``` +info: Installing 1 global package with Node.js +✓ Installed my-cli 1.0.0 + Bins: my-cli +``` + +## `my-cli ran ran` + +``` +my-cli: ran; native-addon: ran +``` + +## `vp update -g my-cli@2.0.0` + +``` +info: Updating 1 global package with Node.js +✓ Updated my-cli to 2.0.0 + Bins: my-cli +warning: Lifecycle scripts were skipped for: my-cli, native-addon. +To allow them, reinstall with: + vp install -g my-cli@2.0.0 --ignore-scripts=false +``` + +## `my-cli skipped skipped` + +``` +my-cli: skipped; native-addon: skipped +``` + +## `vp update -g my-cli@1.0.0 --ignore-scripts=false` + +``` +info: Updating 1 global package with Node.js +✓ Updated my-cli to 1.0.0 + Bins: my-cli +``` + +## `my-cli ran ran` + +``` +my-cli: ran; native-addon: ran +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_npm12.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_npm12.md new file mode 100644 index 0000000000..d35f3ac390 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_npm12.md @@ -0,0 +1,56 @@ +# global_scripts_npm12 + +A case-owned Node runtime with bundled npm 12 still runs all scripts only when explicitly enabled, without changing Node.js. + +## `node setup-npm.cjs` + + +## `node -p 'require(require('\''node:path'\'').join(require('\''node:path'\'').dirname(process.execPath), process.platform === '\''win32'\'' ? '\''node_modules/npm/package.json'\'' : '\''../lib/node_modules/npm/package.json'\'')).version'` + +``` +12.0.2 +``` + +## `vpt mkdir -p tarballs` + + +## `npm pack ./native-addon --ignore-scripts --pack-destination tarballs` + + +## `npm pack ./my-cli --ignore-scripts --pack-destination tarballs` + + +## `vp install -g my-cli@1.0.0` + +``` +VITE+ - The Unified Toolchain for the Web + +info: Installing 1 global package with Node.js +✓ Installed my-cli 1.0.0 + Bins: my-cli +warning: Lifecycle scripts were skipped for: my-cli, native-addon. +To allow them, reinstall with: + vp install -g my-cli@1.0.0 --ignore-scripts=false +``` + +## `my-cli skipped skipped` + +``` +my-cli: skipped; native-addon: skipped +``` + +## `vp install -g my-cli@1.0.0 --ignore-scripts=false` + +``` +VITE+ - The Unified Toolchain for the Web + +info: Installing 1 global package with Node.js +✓ Installed my-cli 1.0.0 + Bins: my-cli +``` + +## `my-cli ran ran` + +``` +my-cli: ran; native-addon: ran +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots.toml index 15b5570dbf..ea854f7d23 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots.toml @@ -33,7 +33,7 @@ steps = [ [[case]] name = "global_install_ignore_scripts" vp = "global" -comment = "Managed global install and add skip dependency lifecycle scripts when requested. Without the flag, scripts still run. The installed binary works in either case." +comment = "Managed global install and add skip dependency lifecycle scripts, including by default. The installed binary works in either case." env = { npm_config_ignore_scripts = "false", npm_config_audit = "false", npm_config_fund = "false" } steps = [ { argv = ["npm", "pack", "./scripted-dep", "--ignore-scripts"], snapshot = false }, @@ -43,8 +43,8 @@ steps = [ { argv = ["vp", "add", "-g", "--ignore-scripts", "./scripted-dep-1.0.0.tgz"], snapshot = false }, ["scripted-dep", "skipped"], { argv = ["vp", "remove", "-g", "scripted-dep"], snapshot = false }, - { argv = ["vp", "install", "-g", "./scripted-dep-1.0.0.tgz"], snapshot = false }, - ["scripted-dep", "ran"], + ["vp", "install", "-g", "./scripted-dep-1.0.0.tgz"], + ["scripted-dep", "skipped"], ] after = [ { argv = ["vp", "remove", "-g", "scripted-dep"], continue-on-failure = true }, diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots/global_install_ignore_scripts.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots/global_install_ignore_scripts.md index 7830dadfdd..0f4ccd5a35 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots/global_install_ignore_scripts.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots/global_install_ignore_scripts.md @@ -1,6 +1,6 @@ # global_install_ignore_scripts -Managed global install and add skip dependency lifecycle scripts when requested. Without the flag, scripts still run. The installed binary works in either case. +Managed global install and add skip dependency lifecycle scripts, including by default. The installed binary works in either case. ## `npm pack ./scripted-dep --ignore-scripts` @@ -31,9 +31,19 @@ postinstall: skipped ## `vp install -g ./scripted-dep-1.0.0.tgz` +``` +VITE+ - The Unified Toolchain for the Web + +info: Installing 1 global package with Node.js +✓ Installed scripted-dep 1.0.0 + Bins: scripted-dep +warning: Lifecycle scripts were skipped for: scripted-dep. +To allow them, reinstall with: + vp install -g ./scripted-dep-1.0.0.tgz --ignore-scripts=false +``` -## `scripted-dep ran` +## `scripted-dep skipped` ``` -postinstall: ran +postinstall: skipped ``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md index 22974d0ba2..56fba5e80a 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md @@ -23,7 +23,7 @@ Options: --prefer-offline Use cached packages when available --offline Only use packages already in cache -f, --force Force reinstall all dependencies - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml index 6862462f47..7a2b0a18bd 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml @@ -11,7 +11,7 @@ steps = [ name = "npm_global_update_notifier" vp = "global" comment = "Global installs disable npm update notifications in the child process." -steps = [["vp", "install", "-g", "./global-package"]] +steps = [["vp", "install", "-g", "./global-package", "--ignore-scripts=false"]] [[case]] name = "npm12_update_notifier" diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md index 8ab0abf4bc..f623219c29 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md @@ -2,7 +2,7 @@ Global installs disable npm update notifications in the child process. -## `vp install -g ./global-package` +## `vp install -g ./global-package --ignore-scripts=false` ``` VITE+ - The Unified Toolchain for the Web diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md index f5b9f60078..c08f48d062 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md @@ -23,7 +23,7 @@ Options: --prefer-offline Use cached packages when available --offline Only use packages already in cache -f, --force Force reinstall all dependencies - --ignore-scripts Do not run lifecycle scripts + --ignore-scripts[=] Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) diff --git a/crates/vp_global_cli/src/cli.rs b/crates/vp_global_cli/src/cli.rs index 6216fef327..8fd6dbbed0 100644 --- a/crates/vp_global_cli/src/cli.rs +++ b/crates/vp_global_cli/src/cli.rs @@ -654,6 +654,7 @@ async fn run_package_manager_command( } Some(ManagedGlobalCommand::Update { packages, + ignore_scripts, latest, concurrency, reinstall_node_mismatch, @@ -667,6 +668,7 @@ async fn run_package_manager_command( } return managed_update( packages, + ignore_scripts, latest, concurrency, reinstall_node_mismatch, @@ -813,6 +815,7 @@ struct NodeMismatchPackage { async fn managed_update( packages: &[String], + ignore_scripts: bool, latest: bool, concurrency: Option, reinstall_node_mismatch: bool, @@ -966,7 +969,7 @@ async fn managed_update( global::install::InstallOptions { node_version: Some(¤t_node_version), force: false, - ignore_scripts: false, + ignore_scripts, concurrency, update: true, }, diff --git a/crates/vp_global_cli/src/commands/global/install.rs b/crates/vp_global_cli/src/commands/global/install.rs index 5a70953c69..fcf3515423 100644 --- a/crates/vp_global_cli/src/commands/global/install.rs +++ b/crates/vp_global_cli/src/commands/global/install.rs @@ -1,7 +1,9 @@ //! Global package installation handling. +#![deny(clippy::print_stdout)] + use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeSet, HashMap, HashSet}, fs::{File, OpenOptions, TryLockError}, io::{Read, Write}, process::Stdio, @@ -44,6 +46,7 @@ struct InstalledPackage { js_bins: HashSet, install_id: String, install_dir: AbsolutePathBuf, + skipped_scripts: Vec, } type InstallError = (Option, Box); @@ -134,6 +137,7 @@ pub async fn install( options: InstallOptions<'_>, ) -> Result<(), InstallError> { let InstallOptions { node_version, force, ignore_scripts, concurrency, update } = options; + let explicit_node = node_version.is_some() && !update; if package_specs.is_empty() { return Ok(()); } @@ -275,6 +279,7 @@ pub async fn install( // 5. Finalize installed packages. let mut bin_owners = HashMap::::new(); + let mut script_warnings = Vec::new(); for (index, (package_name, Package { spec, install })) in packages.into_iter().enumerate() { let lock_file = install_locks.remove(&package_name); let Some(InstalledPackage { @@ -283,6 +288,7 @@ pub async fn install( mut js_bins, install_id, install_dir, + skipped_scripts, }) = install else { continue; @@ -540,11 +546,36 @@ pub async fn install( if index + 1 < packages_count { output::raw(""); } + if !skipped_scripts.is_empty() { + script_warnings.push((spec.to_string(), skipped_scripts)); + } + } + + // Keep recovery instructions after every package's installation summary. + let node_argument = + if explicit_node { format!(" --node {node_version}") } else { String::new() }; + for (spec, skipped) in script_warnings { + let spec = quote_install_argument(&spec); + output::raw_stderr(&format!( + "{} Lifecycle scripts were skipped for: {}.\nTo allow them, reinstall with:\n vp install -g {spec}{node_argument} --ignore-scripts=false", + style("warning:").for_stderr().yellow().bold(), + skipped.join(", "), + )); } if let Some(error) = first_error { Err(error) } else { Ok(()) } } +fn quote_install_argument(argument: &str) -> String { + if argument.bytes().all(|byte| byte.is_ascii_alphanumeric() || b"@/.,:_-".contains(&byte)) { + argument.to_string() + } else if cfg!(windows) { + format!("\"{}\"", argument.replace('"', "\\\"")) + } else { + format!("'{}'", argument.replace('\'', "'\\''")) + } +} + /// Install one package into a unique final prefix. async fn install_one( package_name: &str, @@ -565,8 +596,10 @@ async fn install_one( env.prepend(node_bin_dir, &["node", "npm", "npx"], PrependOptions::default())?; let mut command = Command::new(npm_path.as_path()); command.args(["install", "-g", "--no-fund", &package_spec]); - if ignore_scripts { - command.arg("--ignore-scripts"); + command.arg(if ignore_scripts { "--ignore-scripts" } else { "--ignore-scripts=false" }); + if !ignore_scripts { + // npm 12 also gates scripts by package approval; older npm ignores this setting. + command.env("npm_config_dangerously_allow_all_scripts", "true"); } let output = command .env("npm_config_prefix", install_dir.as_path()) @@ -592,6 +625,19 @@ async fn install_one( } let node_modules_dir = get_node_modules_dir(&install_dir, package_name); + let skipped_scripts = if ignore_scripts { + // --ignore-scripts suppresses npm's blocked-script report, so inspect the installed tree. + collect_skipped_scripts(&get_node_modules_dir(&install_dir, "")).await + } else { + Ok(Vec::new()) + }; + let skipped_scripts = match skipped_scripts { + Ok(skipped) => skipped, + Err(error) => { + cleanup_failed_install(&install_dir).await?; + return Err(error); + } + }; let package_json_path = node_modules_dir.join("package.json"); if !tokio::fs::try_exists(&package_json_path).await.unwrap_or(false) { @@ -634,11 +680,79 @@ async fn install_one( } Ok(( - InstalledPackage { installed_version, bin_names, js_bins, install_id, install_dir }, + InstalledPackage { + installed_version, + bin_names, + js_bins, + install_id, + install_dir, + skipped_scripts, + }, lock_file, )) } +async fn collect_skipped_scripts(node_modules: &AbsolutePath) -> Result, Error> { + let mut pending = vec![node_modules.to_absolute_path_buf()]; + let mut visited = HashSet::new(); + let mut skipped = BTreeSet::new(); + while let Some(directory) = pending.pop() { + let mut entries = match tokio::fs::read_dir(&directory).await { + Ok(entries) => entries, + Err(error) if error.kind() == std::io::ErrorKind::NotFound => continue, + Err(error) => return Err(error.into()), + }; + while let Some(entry) = entries.next_entry().await? { + let file_type = entry.file_type().await?; + if !file_type.is_dir() && !file_type.is_symlink() { + continue; + } + let name = entry.file_name(); + let name = name.to_string_lossy(); + if name.starts_with('.') { + continue; + } + let package_dir = directory.join(name.as_ref()); + if name.starts_with('@') { + pending.push(package_dir); + continue; + } + // Linked local packages can form cycles through their node_modules. + let real_path = tokio::fs::canonicalize(&package_dir).await?; + if !visited.insert(real_path) { + continue; + } + let manifest = match tokio::fs::read(package_dir.join("package.json")).await { + Ok(manifest) => manifest, + Err(error) if error.kind() == std::io::ErrorKind::NotFound => continue, + Err(error) => return Err(error.into()), + }; + let manifest: serde_json::Value = + serde_json::from_slice(&manifest).map_err(|error| { + Error::Other(format!("Failed to read installed package: {error}").into()) + })?; + let scripts = &manifest["scripts"]; + let has_script = + |event: &str| scripts[event].as_str().is_some_and(|script| !script.is_empty()); + let lifecycle = + ["preinstall", "install", "postinstall"].iter().any(|event| has_script(event)); + let prepare = file_type.is_symlink() && has_script("prepare"); + // npm implicitly runs node-gyp when there is no custom preinstall/install hook. + let node_gyp = manifest["gypfile"] != false + && !has_script("preinstall") + && !has_script("install") + && tokio::fs::try_exists(package_dir.join("binding.gyp")).await?; + if (lifecycle || prepare || node_gyp) + && let Some(name) = manifest["name"].as_str() + { + skipped.insert(name.to_string()); + } + pending.push(package_dir.join("node_modules")); + } + } + Ok(skipped.into_iter().collect()) +} + fn new_install_id() -> String { Uuid::new_v4().to_string() } diff --git a/crates/vp_pm_cli/src/cli.rs b/crates/vp_pm_cli/src/cli.rs index 37d0a3ca02..760e19b469 100644 --- a/crates/vp_pm_cli/src/cli.rs +++ b/crates/vp_pm_cli/src/cli.rs @@ -178,6 +178,7 @@ pub enum ManagedGlobalCommand<'a> { /// Update packages in the managed global store. Update { packages: &'a [String], + ignore_scripts: bool, latest: bool, concurrency: Option, reinstall_node_mismatch: bool, @@ -255,6 +256,7 @@ impl PackageManagerCommand { }), Self::Update(args) if args.global => Some(ManagedGlobalCommand::Update { packages: &args.packages, + ignore_scripts: args.ignore_scripts, latest: args.latest, concurrency: args.concurrency, reinstall_node_mismatch: args.reinstall_node_mismatch, @@ -595,6 +597,8 @@ mod tests { vec![command, "-g", "react"], vec![command, "-g", "--ignore-scripts", "react"], vec![command, "-g", "react", "--ignore-scripts"], + vec![command, "-g", "react", "--ignore-scripts=false"], + vec![command, "--ignore-scripts=false", "-g", "react"], ] { let parsed = parse(&input).unwrap(); let Some(ManagedGlobalCommand::Install { ignore_scripts, .. }) = @@ -602,7 +606,7 @@ mod tests { else { panic!("expected managed install command: {input:?}"); }; - assert_eq!(ignore_scripts, input.contains(&"--ignore-scripts"), "{input:?}"); + assert_eq!(ignore_scripts, !input.contains(&"--ignore-scripts=false"), "{input:?}"); } } } diff --git a/crates/vp_pm_cli/src/resolution/commands/add.rs b/crates/vp_pm_cli/src/resolution/commands/add.rs index 5c15e00757..7082dc247d 100644 --- a/crates/vp_pm_cli/src/resolution/commands/add.rs +++ b/crates/vp_pm_cli/src/resolution/commands/add.rs @@ -28,7 +28,18 @@ pub struct AddArgs { pub(crate) allow_build: Option, /// Do not run lifecycle scripts - #[arg(long)] + #[arg( + long, + value_name = "BOOL", + hide_default_value = true, + hide_possible_values = true, + action = clap::ArgAction::Set, + num_args = 0..=1, + require_equals = true, + default_missing_value = "true", + default_value_t = false, + default_value_if("global", "true", "true") + )] pub(crate) ignore_scripts: bool, /// Do not install optionalDependencies diff --git a/crates/vp_pm_cli/src/resolution/commands/install.rs b/crates/vp_pm_cli/src/resolution/commands/install.rs index afa5b93f40..08957cd7a6 100644 --- a/crates/vp_pm_cli/src/resolution/commands/install.rs +++ b/crates/vp_pm_cli/src/resolution/commands/install.rs @@ -49,7 +49,18 @@ pub struct InstallArgs { pub(crate) force: bool, /// Do not run lifecycle scripts - #[arg(long)] + #[arg( + long, + value_name = "BOOL", + hide_default_value = true, + hide_possible_values = true, + action = clap::ArgAction::Set, + num_args = 0..=1, + require_equals = true, + default_missing_value = "true", + default_value_t = false, + default_value_if("global", "true", "true") + )] pub(crate) ignore_scripts: bool, /// Don't read or generate lockfile diff --git a/crates/vp_pm_cli/src/resolution/commands/update.rs b/crates/vp_pm_cli/src/resolution/commands/update.rs index c9e49e2616..63b2d5de2c 100644 --- a/crates/vp_pm_cli/src/resolution/commands/update.rs +++ b/crates/vp_pm_cli/src/resolution/commands/update.rs @@ -16,6 +16,10 @@ pub struct UpdateArgs { #[arg(short = 'g', long)] pub(crate) global: bool, + /// Do not run lifecycle scripts (only with -g) + #[arg(long, value_name = "BOOL", requires = "global", hide_default_value = true, hide_possible_values = true, action = clap::ArgAction::Set, num_args = 0..=1, require_equals = true, default_missing_value = "true", default_value_t = true)] + pub(crate) ignore_scripts: bool, + /// Number of global package updates to run in parallel (only with -g) #[arg(long, requires = "global", value_parser = parse_positive_usize)] pub(crate) concurrency: Option, diff --git a/docs/guide/install.md b/docs/guide/install.md index 0b763ccc50..0f63ca3466 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -126,6 +126,18 @@ Use these commands when you want package-manager-managed tools available outside - `vp list -g` - `vp outdated -g` +Global installs and updates disable lifecycle scripts by default, including scripts of transitive dependencies. If scripts were skipped, Vite+ prints a warning at the end with a reinstall command. + +Use `--ignore-scripts=false` to enable all lifecycle scripts for that invocation, including scripts of transitive dependencies: + +```bash +vp install -g my-cli --ignore-scripts=false +vp add -g my-cli --ignore-scripts=false +vp update -g my-cli --ignore-scripts=false +``` + +This uses the selected Node.js runtime and its bundled npm. The setting is not saved, so repeat it when updating. To repair an already-installed package, use `vp install -g` again, since `vp update -g` skips packages that are already up to date. + #### Add and Remove Use `vp add` and `vp remove` for day-to-day dependency edits instead of editing `package.json` by hand. From 2b519e72752468e3f77b63e4df6379f85358a560 Mon Sep 17 00:00:00 2001 From: Liang Date: Thu, 24 Sep 2026 22:39:03 +0800 Subject: [PATCH 2/9] docs: leave install guide unchanged --- docs/guide/install.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/docs/guide/install.md b/docs/guide/install.md index 0f63ca3466..0b763ccc50 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -126,18 +126,6 @@ Use these commands when you want package-manager-managed tools available outside - `vp list -g` - `vp outdated -g` -Global installs and updates disable lifecycle scripts by default, including scripts of transitive dependencies. If scripts were skipped, Vite+ prints a warning at the end with a reinstall command. - -Use `--ignore-scripts=false` to enable all lifecycle scripts for that invocation, including scripts of transitive dependencies: - -```bash -vp install -g my-cli --ignore-scripts=false -vp add -g my-cli --ignore-scripts=false -vp update -g my-cli --ignore-scripts=false -``` - -This uses the selected Node.js runtime and its bundled npm. The setting is not saved, so repeat it when updating. To repair an already-installed package, use `vp install -g` again, since `vp update -g` skips packages that are already up to date. - #### Add and Remove Use `vp add` and `vp remove` for day-to-day dependency edits instead of editing `package.json` by hand. From 89c24f6e696a1a44f09bceafc74a2f567abbbd12 Mon Sep 17 00:00:00 2001 From: Liang Date: Thu, 24 Sep 2026 22:40:54 +0800 Subject: [PATCH 3/9] docs: restore global lifecycle script guidance --- docs/guide/install.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/guide/install.md b/docs/guide/install.md index 0b763ccc50..0f63ca3466 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -126,6 +126,18 @@ Use these commands when you want package-manager-managed tools available outside - `vp list -g` - `vp outdated -g` +Global installs and updates disable lifecycle scripts by default, including scripts of transitive dependencies. If scripts were skipped, Vite+ prints a warning at the end with a reinstall command. + +Use `--ignore-scripts=false` to enable all lifecycle scripts for that invocation, including scripts of transitive dependencies: + +```bash +vp install -g my-cli --ignore-scripts=false +vp add -g my-cli --ignore-scripts=false +vp update -g my-cli --ignore-scripts=false +``` + +This uses the selected Node.js runtime and its bundled npm. The setting is not saved, so repeat it when updating. To repair an already-installed package, use `vp install -g` again, since `vp update -g` skips packages that are already up to date. + #### Add and Remove Use `vp add` and `vp remove` for day-to-day dependency edits instead of editing `package.json` by hand. From e4a12dd41e017cb9ec2436d87ebb0bebb05429b9 Mon Sep 17 00:00:00 2001 From: Liang Date: Thu, 24 Sep 2026 22:47:16 +0800 Subject: [PATCH 4/9] wip --- docs/guide/install.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/guide/install.md b/docs/guide/install.md index 0f63ca3466..db39d921f2 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -126,6 +126,8 @@ Use these commands when you want package-manager-managed tools available outside - `vp list -g` - `vp outdated -g` +::: details Lifecycle scripts for global packages + Global installs and updates disable lifecycle scripts by default, including scripts of transitive dependencies. If scripts were skipped, Vite+ prints a warning at the end with a reinstall command. Use `--ignore-scripts=false` to enable all lifecycle scripts for that invocation, including scripts of transitive dependencies: @@ -136,7 +138,9 @@ vp add -g my-cli --ignore-scripts=false vp update -g my-cli --ignore-scripts=false ``` -This uses the selected Node.js runtime and its bundled npm. The setting is not saved, so repeat it when updating. To repair an already-installed package, use `vp install -g` again, since `vp update -g` skips packages that are already up to date. +This uses the selected Node.js runtime and its bundled npm. The setting is not saved, so repeat it when updating. To repair an already-installed package, use `vp install -g --ignore-scripts=false` again, since `vp update -g` skips packages that are already up to date. + +::: #### Add and Remove From b5cd19224bd890aca87fb06811e3f86f883d1c8c Mon Sep 17 00:00:00 2001 From: Liang Date: Thu, 24 Sep 2026 22:49:30 +0800 Subject: [PATCH 5/9] fix(cli): preserve ignore-scripts help label --- .../snapshots/cli_helper_message.md | 6 +++--- .../command_add_bun/snapshots/command_add_bun.md | 2 +- .../command_add_npm10/snapshots/command_add_npm10.md | 2 +- .../command_add_npm11/snapshots/command_add_npm11.md | 2 +- .../snapshots/command_add_pnpm10.global.md | 2 +- .../snapshots/command_add_pnpm10.local.md | 2 +- .../snapshots/command_add_pnpm11.md | 2 +- .../snapshots/command_add_pnpm12.md | 2 +- .../command_add_pnpm9/snapshots/command_add_pnpm9.md | 2 +- .../command_add_yarn4/snapshots/command_add_yarn4.md | 2 +- .../snapshots/command_update_bun.md | 2 +- .../snapshots/command_update_pnpm10.global.md | 2 +- .../snapshots/command_update_pnpm10.local.md | 2 +- .../snapshots/command_update_pnpm11.md | 2 +- .../snapshots/npm_install_with_options.md | 2 +- .../snapshots/yarn_install_with_options.md | 2 +- crates/vp_global_cli/src/help.rs | 2 ++ packages/cli/binding/src/cli/help.rs | 11 +++++++++++ 18 files changed, 31 insertions(+), 18 deletions(-) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md index 919fafb986..e1385abc16 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md @@ -115,7 +115,7 @@ Options: --prefer-offline Use cached packages when available --offline Only use packages already in cache -f, --force Force reinstall all dependencies - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) @@ -159,7 +159,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -228,7 +228,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts[=] Do not run lifecycle scripts (only with -g) + --ignore-scripts Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md index cbdfde2bb2..65acc370c9 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md index 5f375fc77c..fa89053e35 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md index 628c217a94..6994f3ef11 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md index 5d93bf4a0c..1d8c2acc5d 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md index 905ff86eb7..2c76ae81bf 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md @@ -30,7 +30,7 @@ Options: Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md index 394142b5d4..f605e1480e 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md index 2ddb82486d..c1c4688e28 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md index d1dfac9ed5..597153f2f6 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md index 3f090f5a19..6e70fbed1c 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md @@ -24,7 +24,7 @@ Options: --save-catalog-name Save the new dependency to the specified catalog name --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md index 09efa01152..ef4437e863 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md @@ -18,7 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts[=] Do not run lifecycle scripts (only with -g) + --ignore-scripts Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md index 91cf7cc870..dba865c8d8 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md @@ -18,7 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts[=] Do not run lifecycle scripts (only with -g) + --ignore-scripts Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md index 6af09259e1..262d72d177 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md @@ -16,7 +16,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts[=] Do not run lifecycle scripts (only with -g) + --ignore-scripts Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md index 9eeead6a59..e5c5397c15 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md @@ -18,7 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts[=] Do not run lifecycle scripts (only with -g) + --ignore-scripts Do not run lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md index 56fba5e80a..22974d0ba2 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md @@ -23,7 +23,7 @@ Options: --prefer-offline Use cached packages when available --offline Only use packages already in cache -f, --force Force reinstall all dependencies - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md index c08f48d062..f5b9f60078 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md @@ -23,7 +23,7 @@ Options: --prefer-offline Use cached packages when available --offline Only use packages already in cache -f, --force Force reinstall all dependencies - --ignore-scripts[=] Do not run lifecycle scripts + --ignore-scripts Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) diff --git a/crates/vp_global_cli/src/help.rs b/crates/vp_global_cli/src/help.rs index 2454a5d0cf..d304a64638 100644 --- a/crates/vp_global_cli/src/help.rs +++ b/crates/vp_global_cli/src/help.rs @@ -537,6 +537,8 @@ pub fn print_unified_clap_help_for_path(command_path: &[&str]) -> bool { _ => return false, }; + // Keep the flag's original help label while accepting explicit boolean values. + let raw_help = raw_help.replace("--ignore-scripts[=]", "--ignore-scripts"); let Some(doc) = parse_clap_help_to_doc(&raw_help) else { return false; }; diff --git a/packages/cli/binding/src/cli/help.rs b/packages/cli/binding/src/cli/help.rs index 002d15c09d..1b4634812d 100644 --- a/packages/cli/binding/src/cli/help.rs +++ b/packages/cli/binding/src/cli/help.rs @@ -14,6 +14,17 @@ use super::types::SynthesizableSubcommand; const GLOBAL_ONLY_SUBCOMMANDS: &[&str] = &["env", "upgrade", "implode"]; pub(super) fn handle_cli_parse_error(err: clap::Error) -> Result { + if matches!(err.kind(), ErrorKind::DisplayHelp) { + let help = err.to_string(); + if help.contains("--ignore-scripts[=]") { + // Hide the optional value without shifting clap's description column. + let help = help.replace("--ignore-scripts[=]\n", "--ignore-scripts\n"); + output::raw( + help.replace("--ignore-scripts[=]", "--ignore-scripts ").trim_end(), + ); + return Ok(ExitStatus(err.exit_code() as u8)); + } + } if matches!(err.kind(), ErrorKind::InvalidSubcommand) && print_invalid_subcommand_error(&err) { return Ok(ExitStatus(err.exit_code() as u8)); } From 797cc760b72a8965d8f45c853479edad39e7d705 Mon Sep 17 00:00:00 2001 From: Liang Date: Thu, 24 Sep 2026 22:55:38 +0800 Subject: [PATCH 6/9] feat(cli): use --run-scripts for global installs --- .../snapshots/cli_helper_message.md | 4 +++- .../snapshots/command_add_bun.md | 1 + .../snapshots/command_add_npm10.md | 1 + .../snapshots/command_add_npm11.md | 1 + .../snapshots/command_add_pnpm10.global.md | 1 + .../snapshots/command_add_pnpm10.local.md | 2 ++ .../snapshots/command_add_pnpm11.md | 1 + .../snapshots/command_add_pnpm12.md | 1 + .../snapshots/command_add_pnpm9.md | 1 + .../snapshots/command_add_yarn4.md | 1 + .../snapshots/command_update_bun.md | 2 +- .../snapshots/command_update_pnpm10.global.md | 2 +- .../snapshots/command_update_pnpm10.local.md | 2 +- .../snapshots/command_update_pnpm11.md | 2 +- .../global_install_scripts/snapshots.toml | 10 +++++----- .../global_scripts_default_and_enable.md | 16 ++++++++-------- .../snapshots/global_scripts_npm12.md | 4 ++-- .../global_install_ignore_scripts.md | 2 +- .../snapshots/npm_install_with_options.md | 1 + .../npm_update_notifier/snapshots.toml | 2 +- .../snapshots/npm_global_update_notifier.md | 2 +- .../snapshots/yarn_install_with_options.md | 1 + .../src/commands/global/install.rs | 2 +- crates/vp_global_cli/src/help.rs | 2 -- crates/vp_pm_cli/src/cli.rs | 19 +++++++++++++------ .../vp_pm_cli/src/resolution/commands/add.rs | 17 +++++------------ .../src/resolution/commands/install.rs | 18 ++++++------------ .../src/resolution/commands/update.rs | 6 +++--- docs/guide/install.md | 10 +++++----- packages/cli/binding/src/cli/help.rs | 11 ----------- 30 files changed, 70 insertions(+), 75 deletions(-) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md index e1385abc16..1e1c738c2e 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md @@ -116,6 +116,7 @@ Options: --offline Only use packages already in cache -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) @@ -160,6 +161,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -228,7 +230,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts Do not run lifecycle scripts (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md index 65acc370c9..4856b44c02 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md @@ -25,6 +25,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md index fa89053e35..a178df71e4 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md @@ -25,6 +25,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md index 6994f3ef11..8741815a4e 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md @@ -25,6 +25,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md index 1d8c2acc5d..d293403c48 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md @@ -25,6 +25,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md index 2c76ae81bf..28e4b749b8 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md @@ -32,6 +32,8 @@ Options: A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts + Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md index f605e1480e..e60afce9d9 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md @@ -25,6 +25,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md index c1c4688e28..c296eb9690 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md @@ -25,6 +25,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md index 597153f2f6..3606ce8454 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md @@ -25,6 +25,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md index 6e70fbed1c..8bfe768d52 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md @@ -25,6 +25,7 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md index ef4437e863..9a698b1f5d 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md @@ -18,7 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts Do not run lifecycle scripts (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md index dba865c8d8..989307569d 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.global.md @@ -18,7 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts Do not run lifecycle scripts (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md index 262d72d177..a99838e161 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm10/snapshots/command_update_pnpm10.local.md @@ -16,7 +16,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts Do not run lifecycle scripts (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md index e5c5397c15..e2895a0fcb 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_pnpm11/snapshots/command_update_pnpm11.md @@ -18,7 +18,7 @@ Arguments: Options: -L, --latest Update to latest version (ignore semver range) -g, --global Update global packages - --ignore-scripts Do not run lifecycle scripts (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) --concurrency Number of global package updates to run in parallel (only with -g) --reinstall-node-mismatch Reinstall up-to-date global packages installed with a different Node.js version --ignore-node-mismatch Skip up-to-date global packages installed with a different Node.js version diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml index 3ab7d01219..8a794868b6 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml @@ -2,7 +2,7 @@ name = "global_scripts_default_and_enable" vp = "global" local-registry = true -comment = "Global installs and updates skip direct and transitive scripts by default and warn last. Explicit false runs all scripts with the selected Node.js, including Node 20." +comment = "Global installs and updates skip direct and transitive scripts by default and warn last. --run-scripts runs all scripts with the selected Node.js, including Node 20." env = { npm_config_ignore_scripts = "false", npm_config_dangerously_allow_all_scripts = "true", npm_config_audit = "false", npm_config_fund = "false" } steps = [ { argv = ["vpt", "mkdir", "-p", "tarballs"], snapshot = false }, @@ -12,16 +12,16 @@ steps = [ { argv = ["npm", "pack", "./my-cli", "--ignore-scripts", "--pack-destination", "tarballs"], snapshot = false }, ["vp", "install", "-g", "my-cli@1.0.0", "native-addon@1.0.0"], ["my-cli", "skipped", "skipped"], - { argv = ["vp", "install", "-g", "my-cli@1.0.0", "--ignore-scripts=false"], envs = [["npm_config_ignore_scripts", "true"], ["npm_config_dangerously_allow_all_scripts", "false"]] }, + { argv = ["vp", "install", "-g", "my-cli@1.0.0", "--run-scripts"], envs = [["npm_config_ignore_scripts", "true"], ["npm_config_dangerously_allow_all_scripts", "false"]] }, ["my-cli", "ran", "ran"], { argv = ["vp", "env", "install", "node@20.19.6"], snapshot = false }, ["vp", "add", "-g", "my-cli@1.0.0", "--node", "20.19.6", "--ignore-scripts"], ["my-cli", "skipped", "skipped"], - ["vp", "add", "-g", "my-cli@1.0.0", "--node", "20.19.6", "--ignore-scripts=false"], + ["vp", "add", "-g", "my-cli@1.0.0", "--node", "20.19.6", "--run-scripts"], ["my-cli", "ran", "ran"], ["vp", "update", "-g", "my-cli@2.0.0"], ["my-cli", "skipped", "skipped"], - ["vp", "update", "-g", "my-cli@1.0.0", "--ignore-scripts=false"], + ["vp", "update", "-g", "my-cli@1.0.0", "--run-scripts"], ["my-cli", "ran", "ran"], ] @@ -40,6 +40,6 @@ steps = [ { argv = ["npm", "pack", "./my-cli", "--ignore-scripts", "--pack-destination", "tarballs"], snapshot = false }, ["vp", "install", "-g", "my-cli@1.0.0"], ["my-cli", "skipped", "skipped"], - ["vp", "install", "-g", "my-cli@1.0.0", "--ignore-scripts=false"], + ["vp", "install", "-g", "my-cli@1.0.0", "--run-scripts"], ["my-cli", "ran", "ran"], ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_default_and_enable.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_default_and_enable.md index f1562c7ab7..676aff1fb4 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_default_and_enable.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_default_and_enable.md @@ -1,6 +1,6 @@ # global_scripts_default_and_enable -Global installs and updates skip direct and transitive scripts by default and warn last. Explicit false runs all scripts with the selected Node.js, including Node 20. +Global installs and updates skip direct and transitive scripts by default and warn last. --run-scripts runs all scripts with the selected Node.js, including Node 20. ## `vpt mkdir -p tarballs` @@ -29,10 +29,10 @@ info: Installing 2 global packages with Node.js ✓ Installed native-addon 1.0.0 warning: Lifecycle scripts were skipped for: my-cli, native-addon. To allow them, reinstall with: - vp install -g my-cli@1.0.0 --ignore-scripts=false + vp install -g my-cli@1.0.0 --run-scripts warning: Lifecycle scripts were skipped for: native-addon. To allow them, reinstall with: - vp install -g native-addon@1.0.0 --ignore-scripts=false + vp install -g native-addon@1.0.0 --run-scripts ``` ## `my-cli skipped skipped` @@ -41,7 +41,7 @@ To allow them, reinstall with: my-cli: skipped; native-addon: skipped ``` -## `npm_config_ignore_scripts=true npm_config_dangerously_allow_all_scripts=false vp install -g my-cli@1.0.0 --ignore-scripts=false` +## `npm_config_ignore_scripts=true npm_config_dangerously_allow_all_scripts=false vp install -g my-cli@1.0.0 --run-scripts` ``` VITE+ - The Unified Toolchain for the Web @@ -68,7 +68,7 @@ info: Installing 1 global package with Node.js Bins: my-cli warning: Lifecycle scripts were skipped for: my-cli, native-addon. To allow them, reinstall with: - vp install -g my-cli@1.0.0 --node --ignore-scripts=false + vp install -g my-cli@1.0.0 --node --run-scripts ``` ## `my-cli skipped skipped` @@ -77,7 +77,7 @@ To allow them, reinstall with: my-cli: skipped; native-addon: skipped ``` -## `vp add -g my-cli@1.0.0 --node 20.19.6 --ignore-scripts=false` +## `vp add -g my-cli@1.0.0 --node 20.19.6 --run-scripts` ``` info: Installing 1 global package with Node.js @@ -99,7 +99,7 @@ info: Updating 1 global package with Node.js Bins: my-cli warning: Lifecycle scripts were skipped for: my-cli, native-addon. To allow them, reinstall with: - vp install -g my-cli@2.0.0 --ignore-scripts=false + vp install -g my-cli@2.0.0 --run-scripts ``` ## `my-cli skipped skipped` @@ -108,7 +108,7 @@ To allow them, reinstall with: my-cli: skipped; native-addon: skipped ``` -## `vp update -g my-cli@1.0.0 --ignore-scripts=false` +## `vp update -g my-cli@1.0.0 --run-scripts` ``` info: Updating 1 global package with Node.js diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_npm12.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_npm12.md index d35f3ac390..1eae8f7066 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_npm12.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_npm12.md @@ -30,7 +30,7 @@ info: Installing 1 global package with Node.js Bins: my-cli warning: Lifecycle scripts were skipped for: my-cli, native-addon. To allow them, reinstall with: - vp install -g my-cli@1.0.0 --ignore-scripts=false + vp install -g my-cli@1.0.0 --run-scripts ``` ## `my-cli skipped skipped` @@ -39,7 +39,7 @@ To allow them, reinstall with: my-cli: skipped; native-addon: skipped ``` -## `vp install -g my-cli@1.0.0 --ignore-scripts=false` +## `vp install -g my-cli@1.0.0 --run-scripts` ``` VITE+ - The Unified Toolchain for the Web diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots/global_install_ignore_scripts.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots/global_install_ignore_scripts.md index 0f4ccd5a35..265c5a0c82 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots/global_install_ignore_scripts.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/install_ignore_scripts/snapshots/global_install_ignore_scripts.md @@ -39,7 +39,7 @@ info: Installing 1 global package with Node.js Bins: scripted-dep warning: Lifecycle scripts were skipped for: scripted-dep. To allow them, reinstall with: - vp install -g ./scripted-dep-1.0.0.tgz --ignore-scripts=false + vp install -g ./scripted-dep-1.0.0.tgz --run-scripts ``` ## `scripted-dep skipped` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md index 22974d0ba2..b55ca3d403 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md @@ -24,6 +24,7 @@ Options: --offline Only use packages already in cache -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml index 7a2b0a18bd..d8181f7a50 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml @@ -11,7 +11,7 @@ steps = [ name = "npm_global_update_notifier" vp = "global" comment = "Global installs disable npm update notifications in the child process." -steps = [["vp", "install", "-g", "./global-package", "--ignore-scripts=false"]] +steps = [["vp", "install", "-g", "./global-package", "--run-scripts"]] [[case]] name = "npm12_update_notifier" diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md index f623219c29..c075c049a6 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md @@ -2,7 +2,7 @@ Global installs disable npm update notifications in the child process. -## `vp install -g ./global-package --ignore-scripts=false` +## `vp install -g ./global-package --run-scripts` ``` VITE+ - The Unified Toolchain for the Web diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md index f5b9f60078..276aaa2452 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md @@ -24,6 +24,7 @@ Options: --offline Only use packages already in cache -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts + --run-scripts Run all lifecycle scripts (only with -g) --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) diff --git a/crates/vp_global_cli/src/commands/global/install.rs b/crates/vp_global_cli/src/commands/global/install.rs index fcf3515423..7c0f1d32ee 100644 --- a/crates/vp_global_cli/src/commands/global/install.rs +++ b/crates/vp_global_cli/src/commands/global/install.rs @@ -557,7 +557,7 @@ pub async fn install( for (spec, skipped) in script_warnings { let spec = quote_install_argument(&spec); output::raw_stderr(&format!( - "{} Lifecycle scripts were skipped for: {}.\nTo allow them, reinstall with:\n vp install -g {spec}{node_argument} --ignore-scripts=false", + "{} Lifecycle scripts were skipped for: {}.\nTo allow them, reinstall with:\n vp install -g {spec}{node_argument} --run-scripts", style("warning:").for_stderr().yellow().bold(), skipped.join(", "), )); diff --git a/crates/vp_global_cli/src/help.rs b/crates/vp_global_cli/src/help.rs index d304a64638..2454a5d0cf 100644 --- a/crates/vp_global_cli/src/help.rs +++ b/crates/vp_global_cli/src/help.rs @@ -537,8 +537,6 @@ pub fn print_unified_clap_help_for_path(command_path: &[&str]) -> bool { _ => return false, }; - // Keep the flag's original help label while accepting explicit boolean values. - let raw_help = raw_help.replace("--ignore-scripts[=]", "--ignore-scripts"); let Some(doc) = parse_clap_help_to_doc(&raw_help) else { return false; }; diff --git a/crates/vp_pm_cli/src/cli.rs b/crates/vp_pm_cli/src/cli.rs index 760e19b469..8bb575b93e 100644 --- a/crates/vp_pm_cli/src/cli.rs +++ b/crates/vp_pm_cli/src/cli.rs @@ -240,14 +240,14 @@ impl PackageManagerCommand { packages: &args.packages, node: args.node.as_deref(), force: args.force, - ignore_scripts: args.ignore_scripts, + ignore_scripts: !args.run_scripts, concurrency: args.concurrency, }), Self::Add(args) if args.global => Some(ManagedGlobalCommand::Install { packages: &args.packages, node: args.node.as_deref(), force: false, - ignore_scripts: args.ignore_scripts, + ignore_scripts: !args.run_scripts, concurrency: args.concurrency, }), Self::Remove(args) if args.global => Some(ManagedGlobalCommand::Remove { @@ -256,7 +256,7 @@ impl PackageManagerCommand { }), Self::Update(args) if args.global => Some(ManagedGlobalCommand::Update { packages: &args.packages, - ignore_scripts: args.ignore_scripts, + ignore_scripts: !args.run_scripts, latest: args.latest, concurrency: args.concurrency, reinstall_node_mismatch: args.reinstall_node_mismatch, @@ -597,8 +597,8 @@ mod tests { vec![command, "-g", "react"], vec![command, "-g", "--ignore-scripts", "react"], vec![command, "-g", "react", "--ignore-scripts"], - vec![command, "-g", "react", "--ignore-scripts=false"], - vec![command, "--ignore-scripts=false", "-g", "react"], + vec![command, "-g", "react", "--run-scripts"], + vec![command, "--run-scripts", "-g", "react"], ] { let parsed = parse(&input).unwrap(); let Some(ManagedGlobalCommand::Install { ignore_scripts, .. }) = @@ -606,7 +606,7 @@ mod tests { else { panic!("expected managed install command: {input:?}"); }; - assert_eq!(ignore_scripts, !input.contains(&"--ignore-scripts=false"), "{input:?}"); + assert_eq!(ignore_scripts, !input.contains(&"--run-scripts"), "{input:?}"); } } } @@ -634,6 +634,13 @@ mod tests { fn validates_managed_global_options() { assert!(parse(&["install", "-g"]).is_err()); assert!(parse(&["add", "--node", "22", "react"]).is_err()); + for command in ["install", "add", "update"] { + assert!(parse(&[command, "--run-scripts", "react"]).is_err()); + assert!(parse(&[command, "-g", "--ignore-scripts=false", "react"]).is_err()); + } + for command in ["install", "add"] { + assert!(parse(&[command, "-g", "--run-scripts", "--ignore-scripts", "react"]).is_err()); + } let install = parse(&["install", "-g", "--node", "22", "--concurrency", "2", "tsx"]).unwrap(); diff --git a/crates/vp_pm_cli/src/resolution/commands/add.rs b/crates/vp_pm_cli/src/resolution/commands/add.rs index 7082dc247d..c619764a58 100644 --- a/crates/vp_pm_cli/src/resolution/commands/add.rs +++ b/crates/vp_pm_cli/src/resolution/commands/add.rs @@ -28,18 +28,7 @@ pub struct AddArgs { pub(crate) allow_build: Option, /// Do not run lifecycle scripts - #[arg( - long, - value_name = "BOOL", - hide_default_value = true, - hide_possible_values = true, - action = clap::ArgAction::Set, - num_args = 0..=1, - require_equals = true, - default_missing_value = "true", - default_value_t = false, - default_value_if("global", "true", "true") - )] + #[arg(long)] pub(crate) ignore_scripts: bool, /// Do not install optionalDependencies @@ -116,6 +105,10 @@ pub struct AddArgs { #[arg(long, requires = "global", value_parser = parse_positive_usize)] pub(crate) concurrency: Option, + /// Run all lifecycle scripts (only with -g) + #[arg(long, requires = "global", conflicts_with = "ignore_scripts")] + pub(crate) run_scripts: bool, + /// Packages to add #[arg(required = true)] pub(crate) packages: Vec, diff --git a/crates/vp_pm_cli/src/resolution/commands/install.rs b/crates/vp_pm_cli/src/resolution/commands/install.rs index 08957cd7a6..0a3e3c82c2 100644 --- a/crates/vp_pm_cli/src/resolution/commands/install.rs +++ b/crates/vp_pm_cli/src/resolution/commands/install.rs @@ -49,18 +49,7 @@ pub struct InstallArgs { pub(crate) force: bool, /// Do not run lifecycle scripts - #[arg( - long, - value_name = "BOOL", - hide_default_value = true, - hide_possible_values = true, - action = clap::ArgAction::Set, - num_args = 0..=1, - require_equals = true, - default_missing_value = "true", - default_value_t = false, - default_value_if("global", "true", "true") - )] + #[arg(long)] pub(crate) ignore_scripts: bool, /// Don't read or generate lockfile @@ -119,6 +108,10 @@ pub struct InstallArgs { #[arg(long, requires = "global", value_parser = parse_positive_usize)] pub(crate) concurrency: Option, + /// Run all lifecycle scripts (only with -g) + #[arg(long, requires = "global", conflicts_with = "ignore_scripts")] + pub(crate) run_scripts: bool, + /// Packages to add (if provided, acts as `vp add`) pub(crate) packages: Vec, @@ -219,6 +212,7 @@ impl InstallArgs { save_catalog: self.save_catalog, allow_build: None, ignore_scripts: self.ignore_scripts, + run_scripts: self.run_scripts, no_optional: self.no_optional, frozen_lockfile: self.frozen_lockfile, no_frozen_lockfile: self.no_frozen_lockfile, diff --git a/crates/vp_pm_cli/src/resolution/commands/update.rs b/crates/vp_pm_cli/src/resolution/commands/update.rs index 63b2d5de2c..2abf4e8770 100644 --- a/crates/vp_pm_cli/src/resolution/commands/update.rs +++ b/crates/vp_pm_cli/src/resolution/commands/update.rs @@ -16,9 +16,9 @@ pub struct UpdateArgs { #[arg(short = 'g', long)] pub(crate) global: bool, - /// Do not run lifecycle scripts (only with -g) - #[arg(long, value_name = "BOOL", requires = "global", hide_default_value = true, hide_possible_values = true, action = clap::ArgAction::Set, num_args = 0..=1, require_equals = true, default_missing_value = "true", default_value_t = true)] - pub(crate) ignore_scripts: bool, + /// Run all lifecycle scripts (only with -g) + #[arg(long, requires = "global")] + pub(crate) run_scripts: bool, /// Number of global package updates to run in parallel (only with -g) #[arg(long, requires = "global", value_parser = parse_positive_usize)] diff --git a/docs/guide/install.md b/docs/guide/install.md index db39d921f2..64769202e2 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -130,15 +130,15 @@ Use these commands when you want package-manager-managed tools available outside Global installs and updates disable lifecycle scripts by default, including scripts of transitive dependencies. If scripts were skipped, Vite+ prints a warning at the end with a reinstall command. -Use `--ignore-scripts=false` to enable all lifecycle scripts for that invocation, including scripts of transitive dependencies: +Use `--run-scripts` to enable all lifecycle scripts for that invocation, including scripts of transitive dependencies: ```bash -vp install -g my-cli --ignore-scripts=false -vp add -g my-cli --ignore-scripts=false -vp update -g my-cli --ignore-scripts=false +vp install -g my-cli --run-scripts +vp add -g my-cli --run-scripts +vp update -g my-cli --run-scripts ``` -This uses the selected Node.js runtime and its bundled npm. The setting is not saved, so repeat it when updating. To repair an already-installed package, use `vp install -g --ignore-scripts=false` again, since `vp update -g` skips packages that are already up to date. +This uses the selected Node.js runtime and its bundled npm. The setting is not saved, so repeat it when updating. To repair an already-installed package, use `vp install -g --run-scripts` again, since `vp update -g` skips packages that are already up to date. ::: diff --git a/packages/cli/binding/src/cli/help.rs b/packages/cli/binding/src/cli/help.rs index 1b4634812d..002d15c09d 100644 --- a/packages/cli/binding/src/cli/help.rs +++ b/packages/cli/binding/src/cli/help.rs @@ -14,17 +14,6 @@ use super::types::SynthesizableSubcommand; const GLOBAL_ONLY_SUBCOMMANDS: &[&str] = &["env", "upgrade", "implode"]; pub(super) fn handle_cli_parse_error(err: clap::Error) -> Result { - if matches!(err.kind(), ErrorKind::DisplayHelp) { - let help = err.to_string(); - if help.contains("--ignore-scripts[=]") { - // Hide the optional value without shifting clap's description column. - let help = help.replace("--ignore-scripts[=]\n", "--ignore-scripts\n"); - output::raw( - help.replace("--ignore-scripts[=]", "--ignore-scripts ").trim_end(), - ); - return Ok(ExitStatus(err.exit_code() as u8)); - } - } if matches!(err.kind(), ErrorKind::InvalidSubcommand) && print_invalid_subcommand_error(&err) { return Ok(ExitStatus(err.exit_code() as u8)); } From 57bc660c38b24ce51fdb12cec362ec1122a842a2 Mon Sep 17 00:00:00 2001 From: Liang Date: Fri, 25 Sep 2026 08:15:32 +0800 Subject: [PATCH 7/9] test(cli): fix global install script snapshots --- .../cli_helper_message/snapshots/cli_helper_message.md | 4 ++-- .../fixtures/command_add_bun/snapshots/command_add_bun.md | 2 +- .../fixtures/command_add_npm10/snapshots/command_add_npm10.md | 2 +- .../fixtures/command_add_npm11/snapshots/command_add_npm11.md | 2 +- .../command_add_pnpm10/snapshots/command_add_pnpm10.global.md | 2 +- .../command_add_pnpm10/snapshots/command_add_pnpm10.local.md | 4 ++-- .../command_add_pnpm11/snapshots/command_add_pnpm11.md | 2 +- .../command_add_pnpm12/snapshots/command_add_pnpm12.md | 2 +- .../fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md | 2 +- .../fixtures/command_add_yarn4/snapshots/command_add_yarn4.md | 2 +- .../fixtures/env_install_interrupt/snapshots.toml | 4 ++-- .../env_install_interrupt/snapshots/env_install_interrupt.md | 4 ++-- .../env_install_interrupt/test-reinstall-interrupt.js | 2 +- .../snapshots/npm_install_with_options.md | 2 +- .../snapshots/yarn_install_with_options.md | 2 +- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md index 1e1c738c2e..a5a37e1b89 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md @@ -116,7 +116,6 @@ Options: --offline Only use packages already in cache -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) @@ -131,6 +130,7 @@ Options: -g, --global Install globally (requires package names) --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install @@ -161,7 +161,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -178,6 +177,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md index 4856b44c02..8cc89cc278 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_bun/snapshots/command_add_bun.md @@ -25,7 +25,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -42,6 +41,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md index a178df71e4..9f46b1e117 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm10/snapshots/command_add_npm10.md @@ -25,7 +25,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -42,6 +41,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md index 8741815a4e..52fb1be760 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_npm11/snapshots/command_add_npm11.md @@ -25,7 +25,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -42,6 +41,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md index d293403c48..b5f0cb67fc 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.global.md @@ -25,7 +25,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -42,6 +41,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md index 28e4b749b8..27d5b4ad97 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm10/snapshots/command_add_pnpm10.local.md @@ -32,8 +32,6 @@ Options: A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts - Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile @@ -66,6 +64,8 @@ Options: Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts + Run all lifecycle scripts (only with -g) -h, --help Print help ``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md index e60afce9d9..fd8f450d36 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm11/snapshots/command_add_pnpm11.md @@ -25,7 +25,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -42,6 +41,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md index c296eb9690..d2d0f0dba1 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm12/snapshots/command_add_pnpm12.md @@ -25,7 +25,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -42,6 +41,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md index 3606ce8454..324728ba22 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md @@ -25,7 +25,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -42,6 +41,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md index 8bfe768d52..4f0d4f22bd 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md @@ -25,7 +25,6 @@ Options: --save-catalog Save the new dependency to the default catalog --allow-build A list of package names allowed to run postinstall --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-optional Do not install optionalDependencies --frozen-lockfile Fail if lockfile needs to be updated --no-frozen-lockfile Allow lockfile updates @@ -42,6 +41,7 @@ Options: -g, --global Install globally --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help Documentation: https://viteplus.dev/guide/install diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/snapshots.toml index 59012dcaf0..d3b23cb9b3 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/snapshots.toml @@ -2,7 +2,7 @@ name = "env_install_interrupt" vp = "global" steps = [ - { argv = ["vp", "install", "-g", "./long-time-install-package"], continue-on-failure = true }, + { argv = ["vp", "install", "-g", "./long-time-install-package", "--run-scripts"], continue-on-failure = true }, { argv = ["long-time-install-package"], continue-on-failure = true }, # snapshot = false: the killed install's partial screen is timing-dependent # (which spinner frame was live when the process tree was terminated). ConPTY @@ -11,7 +11,7 @@ steps = [ { argv = ["node", "test-reinstall-interrupt.js"], comment = "Reinstall but interrupt", snapshot = false, continue-on-failure = true }, { argv = ["long-time-install-package"], comment = "Original package should be still runnable", continue-on-failure = true }, { argv = ["node", "check-stale-packages.js", "--expect-stale"], comment = "Interrupted reinstall should leave stale package", continue-on-failure = true }, - { argv = ["vp", "install", "-g", "./long-time-install-package"], comment = "Successful reinstall should clean stale packages", continue-on-failure = true }, + { argv = ["vp", "install", "-g", "./long-time-install-package", "--run-scripts"], comment = "Successful reinstall should clean stale packages", continue-on-failure = true }, { argv = ["node", "check-stale-packages.js"], continue-on-failure = true }, ] after = [ diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/snapshots/env_install_interrupt.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/snapshots/env_install_interrupt.md index 550c62a6f0..872a3cc452 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/snapshots/env_install_interrupt.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/snapshots/env_install_interrupt.md @@ -1,6 +1,6 @@ # env_install_interrupt -## `vp install -g ./long-time-install-package` +## `vp install -g ./long-time-install-package --run-scripts` ``` VITE+ - The Unified Toolchain for the Web @@ -37,7 +37,7 @@ Interrupted reinstall should leave stale package interrupted stale package exists ``` -## `vp install -g ./long-time-install-package` +## `vp install -g ./long-time-install-package --run-scripts` Successful reinstall should clean stale packages diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/test-reinstall-interrupt.js b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/test-reinstall-interrupt.js index 823e20dfa9..6323aa8227 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/test-reinstall-interrupt.js +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/env_install_interrupt/test-reinstall-interrupt.js @@ -25,7 +25,7 @@ const vpBinary = path.join( 'bin', process.platform === 'win32' ? 'vp.exe' : 'vp', ); -const child = spawn(vpBinary, ['install', '-g', './long-time-install-package'], { +const child = spawn(vpBinary, ['install', '-g', './long-time-install-package', '--run-scripts'], { env: { ...process.env, VP_TEST_INTERRUPT_INSTALL: '1' }, stdio: 'inherit', }); diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md index b55ca3d403..ef08af3c50 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md @@ -24,7 +24,6 @@ Options: --offline Only use packages already in cache -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) @@ -39,6 +38,7 @@ Options: -g, --global Install globally (requires package names) --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help ``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md index 276aaa2452..c6ce592109 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md @@ -24,7 +24,6 @@ Options: --offline Only use packages already in cache -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts - --run-scripts Run all lifecycle scripts (only with -g) --no-lockfile Don't read or generate lockfile --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) @@ -39,6 +38,7 @@ Options: -g, --global Install globally (requires package names) --node Node.js version to use for global installation (only with -g) --concurrency Number of global package installs to run in parallel (only with -g) + --run-scripts Run all lifecycle scripts (only with -g) -h, --help Print help ``` From 05e200213b66fedafeeb03bf85ca0884e17b5ec6 Mon Sep 17 00:00:00 2001 From: Liang Date: Fri, 25 Sep 2026 08:39:04 +0800 Subject: [PATCH 8/9] fix(cli): skip dangling links when scanning global scripts --- .../global_install_scripts/local-cli/cli.cjs | 2 ++ .../local-cli/package.json | 10 ++++++ .../global_install_scripts/snapshots.toml | 12 +++++++ .../global_scripts_dangling_dependency.md | 34 +++++++++++++++++++ .../src/commands/global/install.rs | 7 +++- 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/local-cli/cli.cjs create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/local-cli/package.json create mode 100644 crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_dangling_dependency.md diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/local-cli/cli.cjs b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/local-cli/cli.cjs new file mode 100644 index 0000000000..9a15abe108 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/local-cli/cli.cjs @@ -0,0 +1,2 @@ +#!/usr/bin/env node +console.log('local-cli works'); diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/local-cli/package.json b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/local-cli/package.json new file mode 100644 index 0000000000..f2b69c6716 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/local-cli/package.json @@ -0,0 +1,10 @@ +{ + "name": "local-cli", + "version": "1.0.0", + "bin": { + "local-cli": "cli.cjs" + }, + "scripts": { + "postinstall": "node -e \"require('node:fs').writeFileSync('postinstall-ran', '')\"" + } +} diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml index 8a794868b6..9f0c054cbf 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots.toml @@ -1,3 +1,15 @@ +[[case]] +name = "global_scripts_dangling_dependency" +vp = "global" +comment = "A dangling dependency link in a local package must not prevent global installation or skipped-script warnings." +steps = [ + { argv = ["vpt", "mkdir", "-p", "local-cli/node_modules"], snapshot = false }, + { argv = ["node", "-e", "require('node:fs').symlinkSync(require('node:path').resolve('removed-package'), 'local-cli/node_modules/unused-link', process.platform === 'win32' ? 'junction' : 'dir')"], snapshot = false }, + ["vp", "install", "-g", "./local-cli"], + ["local-cli"], + ["vpt", "stat-file", "local-cli/postinstall-ran", "--assert", "missing"], +] + [[case]] name = "global_scripts_default_and_enable" vp = "global" diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_dangling_dependency.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_dangling_dependency.md new file mode 100644 index 0000000000..cd1a29c0a3 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/global_install_scripts/snapshots/global_scripts_dangling_dependency.md @@ -0,0 +1,34 @@ +# global_scripts_dangling_dependency + +A dangling dependency link in a local package must not prevent global installation or skipped-script warnings. + +## `vpt mkdir -p local-cli/node_modules` + + +## `node -e 'require('\''node:fs'\'').symlinkSync(require('\''node:path'\'').resolve('\''removed-package'\''), '\''local-cli/node_modules/unused-link'\'', process.platform === '\''win32'\'' ? '\''junction'\'' : '\''dir'\'')'` + + +## `vp install -g ./local-cli` + +``` +VITE+ - The Unified Toolchain for the Web + +info: Installing 1 global package with Node.js +✓ Installed local-cli 1.0.0 + Bins: local-cli +warning: Lifecycle scripts were skipped for: local-cli. +To allow them, reinstall with: + vp install -g ./local-cli --run-scripts +``` + +## `local-cli` + +``` +local-cli works +``` + +## `vpt stat-file local-cli/postinstall-ran --assert missing` + +``` +local-cli/postinstall-ran: missing +``` diff --git a/crates/vp_global_cli/src/commands/global/install.rs b/crates/vp_global_cli/src/commands/global/install.rs index 7c0f1d32ee..52223f2dd4 100644 --- a/crates/vp_global_cli/src/commands/global/install.rs +++ b/crates/vp_global_cli/src/commands/global/install.rs @@ -718,7 +718,12 @@ async fn collect_skipped_scripts(node_modules: &AbsolutePath) -> Result real_path, + // Local packages can retain dangling dependency links unrelated to this install. + Err(error) if error.kind() == std::io::ErrorKind::NotFound => continue, + Err(error) => return Err(error.into()), + }; if !visited.insert(real_path) { continue; } From 3e1f0a6e3f27bcf45854d00e66a468408b29c66f Mon Sep 17 00:00:00 2001 From: Liang Date: Fri, 25 Sep 2026 08:40:07 +0800 Subject: [PATCH 9/9] docs(cli): label global install inspection phase --- crates/vp_global_cli/src/commands/global/install.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/vp_global_cli/src/commands/global/install.rs b/crates/vp_global_cli/src/commands/global/install.rs index 52223f2dd4..4ff7405474 100644 --- a/crates/vp_global_cli/src/commands/global/install.rs +++ b/crates/vp_global_cli/src/commands/global/install.rs @@ -624,6 +624,7 @@ async fn install_one( return Err(Error::Other(format!("npm install failed with {}", output.status).into())); } + // 3. Inspect the installed packages for skipped scripts and binary metadata. let node_modules_dir = get_node_modules_dir(&install_dir, package_name); let skipped_scripts = if ignore_scripts { // --ignore-scripts suppresses npm's blocked-script report, so inspect the installed tree.