diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/.npmrc b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/.npmrc new file mode 100644 index 0000000000..7530886147 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/.npmrc @@ -0,0 +1,3 @@ +update-notifier=true +audit=false +fund=false diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/global-package/package.json b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/global-package/package.json new file mode 100644 index 0000000000..2926138f0c --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/global-package/package.json @@ -0,0 +1,8 @@ +{ + "name": "global-update-notifier-test", + "version": "1.0.0", + "private": true, + "scripts": { + "postinstall": "node -e \"require('node:assert/strict').equal(process.env.npm_config_update_notifier, 'false')\"" + } +} diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/package.json b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/package.json new file mode 100644 index 0000000000..c04c31f622 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/package.json @@ -0,0 +1,9 @@ +{ + "name": "npm-update-notifier", + "version": "1.0.0", + "private": true, + "packageManager": "npm@11.13.0", + "scripts": { + "postinstall": "node -e \"console.log('npm_config_update_notifier=' + process.env.npm_config_update_notifier)\"" + } +} 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 new file mode 100644 index 0000000000..6862462f47 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots.toml @@ -0,0 +1,24 @@ +[[case]] +name = "npm11_update_notifier" +vp = "global" +comment = "Managed npm 11 commands disable update notifications even when the project enables them." +steps = [ + ["vp", "pm", "config", "get", "update-notifier"], + ["vp", "install"], +] + +[[case]] +name = "npm_global_update_notifier" +vp = "global" +comment = "Global installs disable npm update notifications in the child process." +steps = [["vp", "install", "-g", "./global-package"]] + +[[case]] +name = "npm12_update_notifier" +vp = "global" +comment = "Managed npm 12 commands disable update notifications even when the project enables them." +steps = [ + { argv = ["vpt", "json-edit", "package.json", "packageManager", "npm@12.0.2"], snapshot = false }, + ["vp", "pm", "config", "get", "update-notifier"], + ["vp", "install"], +] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm11_update_notifier.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm11_update_notifier.md new file mode 100644 index 0000000000..e2f7986251 --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm11_update_notifier.md @@ -0,0 +1,22 @@ +# npm11_update_notifier + +Managed npm 11 commands disable update notifications even when the project enables them. + +## `vp pm config get update-notifier` + +``` +false +``` + +## `vp install` + +``` +VITE+ - The Unified Toolchain for the Web + +> npm-update-notifier@1.0.0 postinstall +> node -e "console.log('npm_config_update_notifier=' + process.env.npm_config_update_notifier)" + +npm_config_update_notifier=false + +up to date in +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm12_update_notifier.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm12_update_notifier.md new file mode 100644 index 0000000000..c9e09949ca --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm12_update_notifier.md @@ -0,0 +1,22 @@ +# npm12_update_notifier + +Managed npm 12 commands disable update notifications even when the project enables them. + +## `vpt json-edit package.json packageManager npm@12.0.2` + + +## `vp pm config get update-notifier` + +``` +false +``` + +## `vp install` + +``` +VITE+ - The Unified Toolchain for the Web + +npm_config_update_notifier=false + +up to date in +``` 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 new file mode 100644 index 0000000000..8ab0abf4bc --- /dev/null +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_update_notifier/snapshots/npm_global_update_notifier.md @@ -0,0 +1,12 @@ +# npm_global_update_notifier + +Global installs disable npm update notifications in the child process. + +## `vp install -g ./global-package` + +``` +VITE+ - The Unified Toolchain for the Web + +info: Installing 1 global package with Node.js +✓ Installed global-update-notifier-test 1.0.0 +``` diff --git a/crates/vp_global_cli/src/commands/global/install.rs b/crates/vp_global_cli/src/commands/global/install.rs index e3c793d290..fe374a0ef9 100644 --- a/crates/vp_global_cli/src/commands/global/install.rs +++ b/crates/vp_global_cli/src/commands/global/install.rs @@ -554,6 +554,7 @@ async fn install_one( let output = Command::new(npm_path.as_path()) .args(["install", "-g", "--no-fund", &package_spec]) .env("npm_config_prefix", install_dir.as_path()) + .env("npm_config_update_notifier", "false") .env("PATH", format_path_prepended(node_bin_dir.as_path())) .stdout(Stdio::piped()) .stderr(Stdio::piped()) diff --git a/crates/vp_pm_cli/src/resolution/command.rs b/crates/vp_pm_cli/src/resolution/command.rs index a5369bd7ba..c81e8188f6 100644 --- a/crates/vp_pm_cli/src/resolution/command.rs +++ b/crates/vp_pm_cli/src/resolution/command.rs @@ -17,12 +17,13 @@ pub(crate) struct ResolvedCommand { impl ResolvedCommand { pub(crate) fn new(program: impl Into) -> Self { - Self { - program: program.into(), - args: Vec::new(), - env: BTreeMap::new(), - pre_run: Vec::new(), + let program = program.into(); + let mut env = BTreeMap::new(); + if matches!(program.as_str(), "npm" | "npx") { + // Include npm/npx fallbacks: Vite+ manages their versions too. + env.insert("npm_config_update_notifier".to_string(), "false".to_string()); } + Self { program, args: Vec::new(), env, pre_run: Vec::new() } } } diff --git a/crates/vp_pm_cli/src/resolution/commands/dlx.rs b/crates/vp_pm_cli/src/resolution/commands/dlx.rs index 5e8ed4537c..c82240fceb 100644 --- a/crates/vp_pm_cli/src/resolution/commands/dlx.rs +++ b/crates/vp_pm_cli/src/resolution/commands/dlx.rs @@ -391,6 +391,10 @@ mod tests { assert_eq!(command.program, "npx"); assert_eq!(command.args, vec!["--yes", "create-vue", "my-app"]); assert_eq!(resolution.diagnostics[0].kind, DiagnosticKind::FallbackCommand); + assert_eq!( + command.env.get("npm_config_update_notifier").map(String::as_str), + Some("false") + ); } #[test] @@ -401,7 +405,10 @@ mod tests { assert_eq!(command.program, "npx"); assert_eq!(command.args, vec!["--yes", "create-vue", "my-app"]); assert!(resolution.diagnostics.is_empty()); - assert!(command.env.is_empty()); + assert_eq!( + command.env.get("npm_config_update_notifier").map(String::as_str), + Some("false") + ); } #[test] diff --git a/crates/vp_pm_cli/src/resolution/commands/whoami.rs b/crates/vp_pm_cli/src/resolution/commands/whoami.rs index d834889f65..d3117868e9 100644 --- a/crates/vp_pm_cli/src/resolution/commands/whoami.rs +++ b/crates/vp_pm_cli/src/resolution/commands/whoami.rs @@ -99,6 +99,10 @@ mod tests { assert_eq!(command.program, "npm"); assert_eq!(command.args, vec!["whoami"]); + assert_eq!( + command.env.get("npm_config_update_notifier").map(String::as_str), + Some("false") + ); } #[test] diff --git a/crates/vp_pm_cli/src/resolution/resolve.rs b/crates/vp_pm_cli/src/resolution/resolve.rs index 0e4f4e7a7a..473df02e47 100644 --- a/crates/vp_pm_cli/src/resolution/resolve.rs +++ b/crates/vp_pm_cli/src/resolution/resolve.rs @@ -127,6 +127,30 @@ mod tests { )); } + #[test] + fn only_npm_installs_disable_npm_update_notifications() { + for (client, version, expected) in [ + (PackageManagerType::Npm, "11.13.0", Some("false")), + (PackageManagerType::Npm, "12.0.2", Some("false")), + (PackageManagerType::Npm, "latest", Some("false")), + (PackageManagerType::Pnpm, "12.3.4", None), + (PackageManagerType::Yarn, "4.0.0", None), + (PackageManagerType::Bun, "1.0.0", None), + ] { + let manager = package_manager(client, version); + let resolution = resolve_for_manager(&manager, InstallArgs::default()).unwrap(); + let CommandResolution::Run(command) = resolution.outcome else { + panic!("expected install command"); + }; + + assert_eq!( + command.env.get("npm_config_update_notifier").map(String::as_str), + expected, + "{client}@{version}" + ); + } + } + #[test] fn only_pnpm_installs_disable_update_notifications() { for (client, version, expected) in [