feat(npm): prompt for global install lifecycle scripts#34850
Conversation
f6798dd to
5d7fdc0
Compare
bartlomieju
left a comment
There was a problem hiding this comment.
The core feature is well put together: the resolve_npm_version_info extraction is a clean refactor, the default is safe (non-tty or a "no" answer means scripts don't run), and the config-merge logic correctly updates an existing allowScripts or appends one. Two things to sort out before this can land, plus a couple of nits.
Scope (main blocker): this PR bundles unrelated WPT-runner changes -- tests/wpt/wpt.ts (+66/-12: stableExpectedFailures, isFlakyExpectation, the flaky-handling refactor) and tests/wpt/runner/expectations/workers.json, under a separate "test(wpt): stabilize worker expectations" commit. They look reasonable on their own, but they have nothing to do with npm lifecycle scripts and should go in their own PR per the focused-scope rule. Please split them out.
CI: no checks have reported yet -- needs to be green before merge.
See inline comments for the transitive-deps limitation and the test-coverage gap.
nits:
maybe_prompt_allow_lifecycle_scriptsparsesNpmPackageReqReference::from_specifierfor theis_err()guard, thenresolve_npm_lifecycle_scripts_package_reqparses the same URL again with?. You could pass the parsed ref through and skip the double parse.VersionReq::parse_from_npm(&version_info.version.to_string())round-trips through a string to build an exact-version req; works, just slightly roundabout.
| || version_info.scripts.contains_key("preinstall") | ||
| || version_info.scripts.contains_key("install") | ||
| || version_info.scripts.contains_key("postinstall"); | ||
| if !has_lifecycle_scripts { |
There was a problem hiding this comment.
Detection only covers the top-level package: has_install_script/scripts reflect only the directly-installed package's own registry metadata, and allow_scripts is then set to Some(vec![that_one_package]). A package whose install scripts live in a transitive dependency (e.g. something depending on esbuild) won't trigger the prompt, and even on a "yes" answer those dep scripts wouldn't be in the allow-list. Is this an intentional first-step limitation? Either way, worth a code comment noting it, and possibly a follow-up issue.
| Ok(()) | ||
| } | ||
|
|
||
| async fn maybe_prompt_allow_lifecycle_scripts( |
There was a problem hiding this comment.
The actual detection/prompt path here is untested. The spec test passes --allow-scripts=... explicitly, so it hits the !matches!(..., None) early return and never reaches resolve_npm_lifecycle_scripts_package_req or confirm; the unit test sets allow_scripts directly. So the feature's core detection logic has no coverage. A spec test that installs a script-package without --allow-scripts (the spec harness is non-tty, so confirm returns None) would exercise detection + the safe-default skip and let you assert the script did not run.
| return currentExpectation; | ||
| } | ||
|
|
||
| function stableExpectedFailures( |
There was a problem hiding this comment.
This WPT-runner refactor (and the workers.json flaky change) is unrelated to the npm lifecycle-scripts feature. Please move it to its own PR -- it's a fine change, just out of scope here, and keeping it separate keeps the review and the squash-merge history focused.
5d7fdc0 to
4617a3b
Compare
Co-Authored-By: Divy Srivastava <me@littledivy.com>
5132e36 to
c9927d2
Compare
Adds lifecycle-script handling for global npm installs by detecting packages with install scripts, prompting before approving them, and writing the resulting allowScripts setting into the hidden per-command config so scripts run in that install's local node_modules instead of the global npm cache.
Adds regression coverage for a global npm install whose bin entry is generated by an install script.
Tests:
Closes #16164
Closes denoland/divybot#458