Skip to content

fix: harden npm global updates - #5

Merged
amanthanvi merged 1 commit into
mainfrom
fix-node-nvm-npm-retries
Jun 19, 2026
Merged

amanthanvi merged 1 commit into
mainfrom
fix-node-nvm-npm-retries

Conversation

@amanthanvi

@amanthanvi amanthanvi commented Jun 19, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • source NVM before resolving npm/ncu/npx for Unix node updates
  • retry npm ERESOLVE once with --legacy-peer-deps while suppressing the expected first-pass error details when retry succeeds
  • retry npm 11 global allow-scripts warnings once using npm's suggested one-shot --allow-scripts=... argument, without changing persistent npm config
  • prep v2.0.2 release metadata and tests

Validation

  • bash -n updates tests/test_cli.sh scripts/*.sh
  • ./scripts/test.sh
  • git diff --check

Local validation gaps

  • ./scripts/lint.sh blocked locally: shellcheck is not installed; shfmt is also unavailable.
  • bash ./scripts/release-build.sh 2.0.2 blocked locally: zip is not installed.
  • pwsh -NoLogo -NoProfile -File tests/test_windows_native.ps1 blocked locally: pwsh is not installed.

CI installs these missing tools on hosted runners.

Summary by Sourcery

Prepare the 2.0.2 release with hardened global npm update behavior and refreshed tests and docs.

Bug Fixes:

  • Ensure global Node updates source NVM-managed npm tooling first on macOS/Linux.
  • Retry npm 11 global installs once with npm's suggested one-shot allow-scripts list without persisting config, and suppress first-pass warnings when the retry succeeds.
  • Suppress initial npm ERESOLVE error details when a legacy-peer-deps retry path succeeds during global npm upgrades.

Enhancements:

  • Document the updated Node module behavior, including NVM sourcing, npm 11 allow-scripts handling, and new 2.0.2 release artifacts.

Documentation:

  • Update README and SPEC to describe NVM-aware npm resolution, npm 11 allow-scripts retries, and the 2.0.2 Windows installer version.

Tests:

  • Extend Unix and Windows test suites to cover NVM sourcing, npm allow-scripts and ERESOLVE retry behavior, and new 2.0.2 self-update flows.

Chores:

  • Bump embedded version metadata and Windows runtime defaults from 2.0.1 to 2.0.2.

Summary by CodeRabbit

Release Notes: v2.0.2

  • Bug Fixes

    • Fixed npm ERESOLVE error message suppression when leveraging peer dependency conflict workarounds
    • Improved npm global install script approval handling to support automatic retry workflows
    • Enhanced Node Version Manager detection to ensure consistent npm tooling resolution
  • Documentation

    • Updated Windows installation instructions and npm update behavior specifications
  • Chores

    • Version bumped to 2.0.2

Copilot AI review requested due to automatic review settings June 19, 2026 20:59
@sourcery-ai

sourcery-ai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Harden npm-based global Node updates by sourcing NVM before resolving npm tooling, adding single-retry handling for npm ERESOLVE and npm 11 allow-scripts prompts, and preparing the v2.0.2 release metadata, docs, and tests across Bash and PowerShell harnesses.

Sequence diagram for hardened npm global Node updates

sequenceDiagram
    actor User
    participant UpdatesCli as updates
    participant NvmEnv as NVM
    participant NpmCheckUpdates as ncu_or_npx
    participant NpmCli as npm

    User->>UpdatesCli: run updates node
    UpdatesCli->>NvmEnv: source nvm.sh
    NvmEnv-->>UpdatesCli: NVM-managed npm/ncu available

    UpdatesCli->>NpmCheckUpdates: ncu / npx npm-check-updates
    NpmCheckUpdates-->>UpdatesCli: upgrade list

    UpdatesCli->>NpmCli: npm install -g <packages>

    alt [npm ERESOLVE]
        UpdatesCli->>NpmCli: npm install -g <packages> --legacy-peer-deps
        NpmCli-->>UpdatesCli: success (first error details suppressed)
    else [no ERESOLVE]
        NpmCli-->>UpdatesCli: success
    end

    opt [npm 11 skipped scripts]
        UpdatesCli->>NpmCli: npm install -g <packages> --allow-scripts=<list>
        NpmCli-->>UpdatesCli: success (one-shot allow-scripts)
    end

    UpdatesCli-->>User: node updates complete
Loading

File-Level Changes

Change Details Files
Extend CLI node update behavior to source NVM on Unix and to handle npm ERESOLVE and npm 11 allow-scripts flows with controlled retries and stderr output.
  • Adjust test stubs for npm and ncu to model allow-scripts prompts and ERESOLVE behavior, including expected retry invocations and suppression of first-pass stderr when retries succeed
  • Add tests to verify that npm is sourced from NVM when $NVM_DIR/nvm.sh or ~/.nvm/nvm.sh exists before resolving npm/ncu/npx binaries
  • Update expectations for node module behavior to include a retry with npm-provided --allow-scripts list and combined allow-scripts+--legacy-peer-deps invocation when applicable
tests/test_cli.sh
Update Windows-native self-update tests and helpers to target the new 2.0.2 release and use version variables consistently instead of hard-coded literals.
  • Bump current and previous release version variables and propagate them through self-update fixture setup and assertions
  • Replace hard-coded version strings in assertions, cache metadata, and payload paths with expressions based on $currentReleaseVersion and $previousReleaseVersion
  • Update the default version used when installing the repo Windows runtime for tests to 2.0.2
tests/test_windows_native.ps1
tests/helpers/windows_test_lib.ps1
Refresh documentation and spec for the node updater and self-update artifacts for the 2.0.2 release.
  • Update README installation snippets and descriptions of the node module to mention NVM sourcing preference and the new 2.0.2 artifacts
  • Document npm 11+ allow-scripts one-shot retry behavior in the README caveats section
  • Clarify SPEC for the node module to describe NVM sourcing, ERESOLVE retry semantics, and allow-scripts retry behavior
README.md
SPEC.md
CHANGELOG.md
Bump the CLI version metadata to v2.0.2 for the PowerShell entrypoint.
  • Update the UpdatesVersion constant to 2.0.2 in the PowerShell main script so self-update and reporting align with the new release
updates-main.ps1

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@amanthanvi, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 36 minutes and 30 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 43a4d1a9-188a-4b3d-84b3-56c609bbd500

📥 Commits

Reviewing files that changed from the base of the PR and between 243d7f1 and 6156b7c.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • README.md
  • SPEC.md
  • install-windows.ps1
  • tests/helpers/windows_test_lib.ps1
  • tests/test_cli.sh
  • tests/test_windows_native.ps1
  • updates
  • updates-main.ps1
📝 Walkthrough

Walkthrough

Version bumped to 2.0.2. The updates shell script gains an init_nvm_node_tools() function that sources nvm.sh and activates a Node context before any npm/ncu operations. The npm global install flow is refactored with new helpers to extract and replay npm's suggested --allow-scripts=... argument as a one-shot retry, complementing the existing --legacy-peer-deps retry for ERESOLVE. Tests, spec, and docs are updated accordingly.

Changes

NVM Init and npm allow-scripts Retry

Layer / File(s) Summary
Spec and docs contract for new retry behaviors
SPEC.md, CHANGELOG.md, README.md
SPEC.md adds NVM sourcing requirement and two retry behaviors (--legacy-peer-deps for ERESOLVE, --allow-scripts for pending scripts); CHANGELOG and README reflect the same for v2.0.2.
NVM initialization function and call sites
updates
Adds NVM_NODE_TOOLS_READY flag and init_nvm_node_tools() that sources nvm.sh and runs nvm use; wired into run_npm_global_install(), resolve_ncu_runner(), and module_node().
npm allow-scripts retry helpers and refactored install flow
updates
Introduces run_npm_global_install_logged, npm_allow_scripts_arg_from_log, and handle_npm_global_install_success; replaces inline install/error flow with helper-based dispatch for both the allow-scripts and ERESOLVE retry paths.
Shell tests for allow-scripts retry and NVM sourcing
tests/test_cli.sh
Extends the ERESOLVE test stub to cover --allow-scripts=opencode-ai,koffi; adds a new test for the full allow-scripts rerun path; adds a test confirming NVM sourcing before npm tool resolution.
Version constants and Windows test updates to 2.0.2
updates, updates-main.ps1, tests/test_cli.sh, tests/helpers/windows_test_lib.ps1, tests/test_windows_native.ps1
Bumps all version constants from 2.0.1 to 2.0.2 and migrates Windows native tests from hardcoded version strings to dynamic $currentReleaseVersion/$previousReleaseVersion variables.

Sequence Diagram(s)

sequenceDiagram
  participant module_node
  participant init_nvm_node_tools
  participant run_npm_global_install
  participant run_npm_global_install_logged
  participant handle_npm_global_install_success
  participant npm_allow_scripts_arg_from_log

  module_node->>init_nvm_node_tools: source nvm.sh, nvm use
  module_node->>run_npm_global_install: install package
  run_npm_global_install->>init_nvm_node_tools: ensure NVM ready (idempotent)
  run_npm_global_install->>run_npm_global_install_logged: npm install -g <pkg> → error log
  alt exit 0
    run_npm_global_install->>handle_npm_global_install_success: check log
    handle_npm_global_install_success->>npm_allow_scripts_arg_from_log: extract --allow-scripts=...
    npm_allow_scripts_arg_from_log-->>handle_npm_global_install_success: arg or empty
    opt arg present
      handle_npm_global_install_success->>run_npm_global_install_logged: retry with --allow-scripts=...
    end
  else ERESOLVE
    run_npm_global_install->>run_npm_global_install_logged: retry --legacy-peer-deps
    run_npm_global_install_logged-->>handle_npm_global_install_success: result
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • amanthanvi/updates#4: Introduced the original ERESOLVE → --legacy-peer-deps retry logic that this PR extends with the --allow-scripts retry path and NVM initialization.

Poem

🐇 Hop, hop, the scripts now know,
When NVM's around, let it flow!
npm scripts need approval? No fuss—
One retry with allow-scripts, handled for us.
Version two-point-oh-two ships today,
The bunny's proud to hop on its way! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title directly and concisely describes the main change: hardening npm global updates through improved retry logic and NVM sourcing.
Description check ✅ Passed The pull request description comprehensively covers the changes with a clear summary, detailed validation steps, and acknowledgment of local validation gaps with explanation that CI will cover those checks.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-node-nvm-npm-retries

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 243d7f150a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread updates
Comment thread tests/test_windows_native.ps1
@amanthanvi
amanthanvi force-pushed the fix-node-nvm-npm-retries branch from 243d7f1 to 152ff3b Compare June 19, 2026 21:03
@amanthanvi

Copy link
Copy Markdown
Owner Author

@greptile review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the node module’s global npm update flow in the updates Bash CLI (macOS/Linux) by preferring NVM-managed tooling in non-interactive runs and adding targeted retry behavior for common npm failure/warning cases. It also bumps release metadata to v2.0.2 and refreshes docs/tests accordingly.

Changes:

  • Source NVM (when present) before resolving/running npm/ncu/npx for the node module.
  • Add retry logic for npm ERESOLVE (--legacy-peer-deps) and npm 11 “allow-scripts” one-shot guidance, suppressing first-pass details when a retry succeeds.
  • Bump versions to 2.0.2 across the Bash/PowerShell entrypoints, docs, changelog, and tests.

Reviewed changes

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

Show a summary per file
File Description
updates-main.ps1 Bumps embedded Windows payload version to 2.0.2.
updates Adds NVM sourcing + npm retry logic for global installs in the node module.
tests/test_windows_native.ps1 Updates Windows native self-update tests for the 2.0.2 release.
tests/test_cli.sh Adds/updates Unix CLI tests covering npm retry behavior and NVM sourcing.
tests/helpers/windows_test_lib.ps1 Updates default Windows runtime version used by tests to 2.0.2.
SPEC.md Documents NVM sourcing and npm retry behavior for the node module.
README.md Updates Windows install snippet/version and node module description.
CHANGELOG.md Adds 2.0.2 release notes describing the hardened npm flow.

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

Comment thread updates
Comment thread README.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/test_windows_native.ps1 (1)

991-991: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Incomplete variable migration causes test assertion mismatch.

This test installs $previousReleaseVersion (2.0.1) on line 939, but asserts that current.txt still contains the hardcoded '2.0.0'. The assertion should use $previousReleaseVersion to match the installed version.

The same issue occurs at lines 1138, 1226, and 1309 in other self-update failure tests.

🔧 Proposed fix for all four test assertions

Line 991:

-            Assert-Equal -Expected '2.0.0' -Actual ((Get-Content -LiteralPath (Join-Path $installRoot 'current.txt') -Raw).Trim()) -Message 'unsupported cached manifest digest should leave current.txt unchanged'
+            Assert-Equal -Expected $previousReleaseVersion -Actual ((Get-Content -LiteralPath (Join-Path $installRoot 'current.txt') -Raw).Trim()) -Message 'unsupported cached manifest digest should leave current.txt unchanged'

Line 1138:

-            Assert-Equal -Expected '2.0.0' -Actual ((Get-Content -LiteralPath (Join-Path $installRoot 'current.txt') -Raw).Trim()) -Message 'download failure should leave current.txt unchanged'
+            Assert-Equal -Expected $previousReleaseVersion -Actual ((Get-Content -LiteralPath (Join-Path $installRoot 'current.txt') -Raw).Trim()) -Message 'download failure should leave current.txt unchanged'

Line 1226:

-            Assert-Equal -Expected '2.0.0' -Actual ((Get-Content -LiteralPath (Join-Path $installRoot 'current.txt') -Raw).Trim()) -Message 'digest mismatch should leave current.txt unchanged'
+            Assert-Equal -Expected $previousReleaseVersion -Actual ((Get-Content -LiteralPath (Join-Path $installRoot 'current.txt') -Raw).Trim()) -Message 'digest mismatch should leave current.txt unchanged'

Line 1309:

-            Assert-Equal -Expected '2.0.0' -Actual ((Get-Content -LiteralPath (Join-Path $installRoot 'current.txt') -Raw).Trim()) -Message 'invalid extracted manifest should leave current.txt unchanged'
+            Assert-Equal -Expected $previousReleaseVersion -Actual ((Get-Content -LiteralPath (Join-Path $installRoot 'current.txt') -Raw).Trim()) -Message 'invalid extracted manifest should leave current.txt unchanged'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_windows_native.ps1` at line 991, In the test file, four
Assert-Equal assertions check that current.txt remains unchanged after
installation failures, but they use hardcoded '2.0.0' as the expected value
instead of the actual installed version. Update the -Expected parameter in all
four Assert-Equal calls (at the mentioned line locations) to use the
$previousReleaseVersion variable instead of the hardcoded '2.0.0' string value
to ensure the assertions match the version that was actually installed earlier
in the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@updates`:
- Around line 738-741: Update the sed pattern in the
npm_allow_scripts_arg_from_log() function to make backticks optional rather than
required, since npm 11+ does not consistently wrap the --allow-scripts
suggestion in backticks. Modify the pattern to match the --allow-scripts flag
whether it appears with backticks (e.g., `npm install -g --allow-scripts=...`)
or without (e.g., npm install -g --allow-scripts=...), and test the updated
pattern against actual npm 11.x stderr output to verify it reliably captures the
flag value in both formats and variations.

---

Outside diff comments:
In `@tests/test_windows_native.ps1`:
- Line 991: In the test file, four Assert-Equal assertions check that
current.txt remains unchanged after installation failures, but they use
hardcoded '2.0.0' as the expected value instead of the actual installed version.
Update the -Expected parameter in all four Assert-Equal calls (at the mentioned
line locations) to use the $previousReleaseVersion variable instead of the
hardcoded '2.0.0' string value to ensure the assertions match the version that
was actually installed earlier in the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 62fc95f7-beb4-4952-afc8-cf2f99b6c54b

📥 Commits

Reviewing files that changed from the base of the PR and between eb2e887 and 243d7f1.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • README.md
  • SPEC.md
  • tests/helpers/windows_test_lib.ps1
  • tests/test_cli.sh
  • tests/test_windows_native.ps1
  • updates
  • updates-main.ps1
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: copilot-pull-request-reviewer
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (5)
**/CHANGELOG.md

📄 CodeRabbit inference engine (AGENTS.md)

Add a CHANGELOG.md entry for each release

Files:

  • CHANGELOG.md
**/SPEC.md

📄 CodeRabbit inference engine (AGENTS.md)

Maintain SPEC.md as living contract for flags/output/modules

Files:

  • SPEC.md
**/*.sh

📄 CodeRabbit inference engine (AGENTS.md)

**/*.sh: Validate scripts using ./scripts/lint.sh which runs bash -n, shellcheck, and shfmt -d
Assume Bash 3.2 compatibility (macOS system Bash); avoid Bash 4+ features
Prefer --dry-run support for anything that might mutate state
Start every logical section with a triple-hash banner: ### SECTION: <name> — <description>

Files:

  • tests/test_cli.sh
**/tests/**/*.sh

📄 CodeRabbit inference engine (AGENTS.md)

**/tests/**/*.sh: Run tests via ./scripts/test.sh which executes ./tests/test_cli.sh
Keep output stable and easy to parse; prefer --no-emoji in tests

Files:

  • tests/test_cli.sh
**/updates

📄 CodeRabbit inference engine (AGENTS.md)

**/updates: Don't print success messages for failed commands in the updates script
Add new functionality as a module function (module_<name>()) and register it in is_module_known(), module_description(), list_modules(), and run_selected_modules()
Modules must be auto-detected and skip gracefully if the backing command is missing, unless --only is used (then missing deps are an error)
For --json contract: stdout must be JSONL-only; route human output to stderr
Keep UPDATES_VERSION in updates aligned with the latest release tag
Use config_set_bool for adding boolean config keys in the updates script

Files:

  • updates
🔇 Additional comments (8)
updates-main.ps1 (1)

22-22: LGTM!

tests/helpers/windows_test_lib.ps1 (1)

612-612: LGTM!

tests/test_windows_native.ps1 (1)

17-18: LGTM!

SPEC.md (1)

462-466: LGTM!

CHANGELOG.md (1)

10-16: LGTM!

README.md (1)

32-35: LGTM!

Also applies to: 91-92, 132-133, 157-160

updates (1)

9-9: LGTM!

Also applies to: 121-121, 676-737, 743-907, 2717-2767

tests/test_cli.sh (1)

26-27: LGTM!

Also applies to: 944-971, 997-1043

Comment thread updates
@amanthanvi
amanthanvi force-pushed the fix-node-nvm-npm-retries branch from 152ff3b to 9d817df Compare June 19, 2026 21:05
@greptile-apps

greptile-apps Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR hardens the Unix updates script and its Windows PowerShell counterpart for npm global installs: it sources NVM before resolving npm/ncu/npx, retries installs that produce npm 11 allow-scripts warnings using the flag npm itself suggests, and suppresses the first-pass error output when an ERESOLVE retry succeeds. It also bumps the version to 2.0.2 and extends both test suites to cover the new retry paths.

  • NVM sourcing (init_nvm_node_tools): guards with NVM_NODE_TOOLS_READY, saves/restores shell options around nvm.sh source, and calls nvm use default only when the npm on PATH isn't already inside the NVM directory.
  • allow-scripts retry: on a successful install that emits an npm warn allow-scripts line, the --allow-scripts=… flag is parsed from npm's own warning and the install is rerun once; if the flag cannot be parsed, a fallback warning is surfaced without guessing.
  • ERESOLVE retry: the first-pass error log is now deleted before the retry runs so it isn't printed when the retry succeeds; however this also suppresses it when the retry fails (see inline comments).

Confidence Score: 4/5

Safe to merge with awareness of one diagnostic regression in the double-failure path.

The allow-scripts retry and NVM init logic are correct and well-tested. The one concern is that the ERESOLVE error log is deleted before the --legacy-peer-deps retry runs; if that retry also fails the original diagnostic is permanently gone. Pre-PR behaviour always printed the original error before retrying, so a user facing a doubly-failed install now sees only the retry's output. Both the Bash and PowerShell paths share this gap.

The ERESOLVE retry block in updates (around the rm -f "$npm_err_log" before the retry) and the matching block in updates-main.ps1 (Invoke-NpmGlobalInstall) deserve a second look to decide whether the original error should be shown when the retry also fails.

Important Files Changed

Filename Overview
updates Core Bash script: adds NVM init, allow-scripts retry, and ERESOLVE retry hardening. When the ERESOLVE retry itself fails, the original error log is deleted before the retry runs, so only the retry's output is shown — original ERESOLVE details are lost.
updates-main.ps1 PowerShell payload: mirrors Bash allow-scripts and ERESOLVE retry logic. Same diagnostic regression — $installResult (original ERESOLVE output) is never printed when the --legacy-peer-deps retry also fails.
tests/test_cli.sh Adds Unix tests for NVM sourcing, allow-scripts retry (with and without parseable flag), and ERESOLVE suppression. Tests are well-structured and cover main success paths.
tests/test_windows_native.ps1 Adds Windows tests for allow-scripts retry, unparseable warning surfacing, and parametrises existing self-update tests to use $currentReleaseVersion/$previousReleaseVersion variables.
tests/helpers/windows_test_lib.ps1 Adds Assert-NotMatch helper and bumps default test version to 2.0.2. Straightforward.
install-windows.ps1 Version default bumped from 2.0.1 to 2.0.2. Trivial change.
CHANGELOG.md Adds v2.0.2 entry documenting NVM sourcing, allow-scripts retry, and ERESOLVE suppression fixes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[run_npm_global_install pkg...] --> B[init_nvm_node_tools]
    B --> C{mktemp ok?}
    C -- no --> D[run npm install -g -- pkg]
    C -- yes --> E[run_npm_global_install_logged err_log -- pkg]
    E --> F{exit 0?}
    F -- yes --> G[handle_npm_global_install_success err_log -- pkg]
    G --> H{allow-scripts arg in log?}
    H -- yes --> I[warn: retrying with allow-scripts]
    I --> J[run_npm_global_install_logged allow_log allow-scripts-arg -- pkg]
    J --> K[show allow_log, return status]
    H -- no --> L{allow-scripts warning unparseable?}
    L -- yes --> M[warn: could not parse list, show err_log, return 0]
    L -- no --> N[show err_log, return 0]
    F -- no --> O{ERESOLVE in log?}
    O -- no --> P[show err_log, return status]
    O -- yes --> Q[warn: retrying --legacy-peer-deps, rm err_log]
    Q --> R[run_npm_global_install_logged new_log --legacy-peer-deps -- pkg]
    R --> S{exit 0?}
    S -- yes --> T[handle_npm_global_install_success new_log --legacy-peer-deps -- pkg]
    S -- no --> U[show new_log only, original ERESOLVE lost, return status]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[run_npm_global_install pkg...] --> B[init_nvm_node_tools]
    B --> C{mktemp ok?}
    C -- no --> D[run npm install -g -- pkg]
    C -- yes --> E[run_npm_global_install_logged err_log -- pkg]
    E --> F{exit 0?}
    F -- yes --> G[handle_npm_global_install_success err_log -- pkg]
    G --> H{allow-scripts arg in log?}
    H -- yes --> I[warn: retrying with allow-scripts]
    I --> J[run_npm_global_install_logged allow_log allow-scripts-arg -- pkg]
    J --> K[show allow_log, return status]
    H -- no --> L{allow-scripts warning unparseable?}
    L -- yes --> M[warn: could not parse list, show err_log, return 0]
    L -- no --> N[show err_log, return 0]
    F -- no --> O{ERESOLVE in log?}
    O -- no --> P[show err_log, return status]
    O -- yes --> Q[warn: retrying --legacy-peer-deps, rm err_log]
    Q --> R[run_npm_global_install_logged new_log --legacy-peer-deps -- pkg]
    R --> S{exit 0?}
    S -- yes --> T[handle_npm_global_install_success new_log --legacy-peer-deps -- pkg]
    S -- no --> U[show new_log only, original ERESOLVE lost, return status]
Loading

Fix All in Codex Fix All in Claude Code Fix All in Cursor

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
updates:699-716
**Original ERESOLVE details silently discarded when retry also fails**

The original `npm_err_log` is deleted (line 701) before the retry runs, so its ERESOLVE output is permanently gone. If the `--legacy-peer-deps` retry then also fails (non-zero `status`), only the retry's error is shown — the original diagnostic is lost. Before this PR, the original error was always printed before the retry ran, so a user would see the full failure chain.

The PR description says "suppress the expected first-pass error details when retry *succeeds*," but the implementation suppresses them even when the retry fails. Concretely: a user who upgrades a package, hits an ERESOLVE, and also hits a different network/auth error on the retry will see only the secondary error, with no indication of what the root-cause ERESOLVE was.

### Issue 2 of 2
updates-main.ps1:835-843
**PowerShell mirrors the same diagnostic loss on retry failure**

`$installResult` (containing the original ERESOLVE output) is never written when the `--legacy-peer-deps` retry fails. `Write-ProcessResultOutput -Result $retryResult` at line 842 shows only the retry's output; `$installResult` is silently dropped. This is the same regression as in the Bash path: users who need to diagnose a doubly-failed install see only the retry's error, not the original ERESOLVE details that triggered the retry.

Reviews (6): Last reviewed commit: "fix: harden npm global updates" | Re-trigger Greptile

Comment thread updates
Comment thread updates Outdated
Comment thread updates Outdated
@amanthanvi

Copy link
Copy Markdown
Owner Author

@greptile review

@amanthanvi
amanthanvi force-pushed the fix-node-nvm-npm-retries branch from 9d817df to 3c5197b Compare June 19, 2026 21:09
@amanthanvi

Copy link
Copy Markdown
Owner Author

@greptile review
@coderabbitai review
@sourcery-ai review
@codex review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

@amanthanvi Sure, I'll review the changes in this PR!

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@greptile-apps

greptile-apps Bot commented Jun 19, 2026

Copy link
Copy Markdown

Greptile Summary

This PR hardens the node module's global npm install flow with two new retry mechanisms — an allow-scripts one-shot retry and NVM sourcing before tool resolution — and bumps the version to 2.0.2 across all metadata files.

  • NVM sourcing (init_nvm_node_tools) is now called from module_node, resolve_ncu_runner, and run_npm_global_install with an idempotency flag, ensuring NVM-managed npm/ncu are preferred in non-interactive shells.
  • run_npm_global_install is refactored into helper functions (run_npm_global_install_logged, npm_allow_scripts_arg_from_log, handle_npm_global_install_success) to separate logging, allow-scripts extraction, and retry logic; the ERESOLVE retry path now also supports a compound allow-scripts+legacy-peer-deps retry.
  • Version bumps and matching test fixture updates span updates, updates-main.ps1, and the Windows test helper.

Confidence Score: 4/5

Safe to merge; the new retry logic is well-tested and the fallback paths (mktemp failure, no NVM dir, ERESOLVE+allow-scripts compound case) are all covered.

The sed pattern in npm_allow_scripts_arg_from_log silently does nothing if npm ever changes its warning text — the retry simply won't fire and the raw npm warning is shown instead. This is a latent fragility, not a current breakage, and the overall retry chain works correctly for the npm 11 format being targeted.

The core logic in updates (the bash script), specifically the npm_allow_scripts_arg_from_log / handle_npm_global_install_success helpers, warrants a second look to confirm acceptable coupling to npm's warning message format.

Important Files Changed

Filename Overview
updates Core bash script: adds init_nvm_node_tools, refactors run_npm_global_install into logged/success helpers with ERESOLVE and allow-scripts retry chains. Logic is sound; one fragility in the sed-based allow-scripts extraction.
tests/test_cli.sh Adds NVM sourcing test, allow-scripts retry test, and extended ERESOLVE+allow-scripts combined test; version constants bumped to 2.0.2/2.0.3. NVM_DIR is correctly unset at test start to prevent CI interference.
tests/test_windows_native.ps1 All hardcoded version literals replaced with $currentReleaseVersion/$previousReleaseVersion variables; self-update fixture and assertion patterns updated to 2.0.2. Clean mechanical bump with no logic changes.
tests/helpers/windows_test_lib.ps1 Single default parameter version bump from 2.0.1 to 2.0.2 in Install-RepoWindowsRuntime.
updates-main.ps1 Version string bumped from 2.0.1 to 2.0.2; no other changes.
CHANGELOG.md New 2.0.2 section added with three fixed entries matching the PR changes.
README.md Version references updated to 2.0.2; node module description updated to document NVM sourcing and npm 11 allow-scripts retry behavior.
SPEC.md Node module spec updated with NVM sourcing, ERESOLVE retry, and allow-scripts retry behavior. Accurately reflects the implementation.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[run_npm_global_install] --> B[init_nvm_node_tools]
    B --> C{DRY_RUN?}
    C -- yes --> D[run npm install -g]
    C -- no --> E[mktemp npm_err_log]
    E --> F[run_npm_global_install_logged\nfirst attempt]
    F --> G{exit 0?}
    G -- yes --> H[handle_npm_global_install_success\nnpm_err_log]
    H --> I{allow-scripts\nwarning in log?}
    I -- no --> J[cat log if non-empty, return 0]
    I -- yes --> K[rm first-pass log\nmktemp allow_err_log]
    K --> L[run_npm_global_install_logged\nwith allow-scripts arg]
    L --> M[cat allow_err_log, return status]
    G -- no --> N{ERESOLVE\nin log?}
    N -- no --> O[cat log, return status]
    N -- yes --> P[rm ERESOLVE log\nmktemp new log\nwarn: retrying with legacy-peer-deps]
    P --> Q[run_npm_global_install_logged\n--legacy-peer-deps retry]
    Q --> R{exit 0?}
    R -- yes --> S[handle_npm_global_install_success\n--legacy-peer-deps path]
    S --> T{allow-scripts\nwarning in log?}
    T -- yes --> U[run_npm_global_install_logged\n--allow-scripts + --legacy-peer-deps]
    T -- no --> V[cat log, return 0]
    R -- no --> W[cat log, return status]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[run_npm_global_install] --> B[init_nvm_node_tools]
    B --> C{DRY_RUN?}
    C -- yes --> D[run npm install -g]
    C -- no --> E[mktemp npm_err_log]
    E --> F[run_npm_global_install_logged\nfirst attempt]
    F --> G{exit 0?}
    G -- yes --> H[handle_npm_global_install_success\nnpm_err_log]
    H --> I{allow-scripts\nwarning in log?}
    I -- no --> J[cat log if non-empty, return 0]
    I -- yes --> K[rm first-pass log\nmktemp allow_err_log]
    K --> L[run_npm_global_install_logged\nwith allow-scripts arg]
    L --> M[cat allow_err_log, return status]
    G -- no --> N{ERESOLVE\nin log?}
    N -- no --> O[cat log, return status]
    N -- yes --> P[rm ERESOLVE log\nmktemp new log\nwarn: retrying with legacy-peer-deps]
    P --> Q[run_npm_global_install_logged\n--legacy-peer-deps retry]
    Q --> R{exit 0?}
    R -- yes --> S[handle_npm_global_install_success\n--legacy-peer-deps path]
    S --> T{allow-scripts\nwarning in log?}
    T -- yes --> U[run_npm_global_install_logged\n--allow-scripts + --legacy-peer-deps]
    T -- no --> V[cat log, return 0]
    R -- no --> W[cat log, return status]
Loading

Fix All in Codex Fix All in Claude Code Fix All in Cursor

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
updates:738-741
**`sed` pattern coupled to npm's exact warning message format**

`npm_allow_scripts_arg_from_log` extracts the `--allow-scripts=...` argument by matching the literal string `` `npm install -g `` inside the warning line. If npm changes the warning text (e.g., drops the backtick-quoted command, renames the flag, or adjusts whitespace), the pattern returns an empty string and the retry silently never fires — the raw `npm warn allow-scripts` warning is then printed to the user without any retry attempt. There is no fallback or log message indicating that the retry was skipped.

Reviews (3): Last reviewed commit: "fix: harden npm global updates" | Re-trigger Greptile

Comment thread updates

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c5197b2de

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread SPEC.md
@amanthanvi
amanthanvi force-pushed the fix-node-nvm-npm-retries branch from 3c5197b to a92d20a Compare June 19, 2026 21:18
@amanthanvi

Copy link
Copy Markdown
Owner Author

@greptile review
@coderabbitai review
@sourcery-ai review
@codex review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

@amanthanvi Sure, I'll review the changes in this PR!

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@amanthanvi
amanthanvi force-pushed the fix-node-nvm-npm-retries branch from a92d20a to 6156b7c Compare June 19, 2026 21:22
@amanthanvi

Copy link
Copy Markdown
Owner Author

@greptile review
@coderabbitai review
@sourcery-ai review
@codex review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

@amanthanvi Sure, I'll review the changes in this PR!

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6156b7c2a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread updates

npm_allow_scripts_arg_from_log() {
local npm_err_log="$1"
sed -n 's/.*\(--allow-scripts=[^`[:space:]]*\).*/\1/p' "$npm_err_log" | head -n 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict allow-scripts parsing to npm warnings

Because this helper scans the entire npm error log before verifying that the text came from an npm warn allow-scripts advisory, a successful install that prints an unrelated warning/deprecation message containing --allow-scripts=foo is retried as npm install -g --allow-scripts=foo .... npm documents this flag as the global-install mechanism for allowing install scripts, so this can approve/run scripts based on arbitrary package-controlled output rather than npm's approval warning; scope extraction to the allow-scripts warning line and mirror the fix in updates-main.ps1.

Useful? React with 👍 / 👎.

@amanthanvi
amanthanvi merged commit 6d43f04 into main Jun 19, 2026
4 checks passed
@amanthanvi
amanthanvi deleted the fix-node-nvm-npm-retries branch June 19, 2026 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants