fix(install): stage installer to tmpfile when invoked via curl|bash (#4414)#4467
Conversation
…4414) The sg(1) re-exec added in #4419 only fires when [ -f "$self" ] succeeds, which means it skips the literal `curl ... | bash` repro from #4414: BASH_SOURCE[0] is empty and $0="bash", so there's no script file to point re-exec at and the script falls through to the legacy newgrp/re-curl path. Stage the script to a tmpfile early in the entry guard by re-curling the canonical URL (overridable via NEMOCLAW_INSTALLER_URL), then exec bash on the staged file. ensure_docker now sees BASH_SOURCE[0] pointing at a real file and the sg(1) re-exec from #4419 can finish the install in a single non-interactive invocation. Guards: - only fires when BASH_SOURCE is empty (pipe mode) - NEMOCLAW_INSTALLER_STAGED=1 one-shot loop guard - mktemp/curl/empty-download failures fall through to legacy direct-main - staged tmpfile auto-cleaned on EXIT via _cleanup_files Verified on Ubuntu 22.04 brev box that #4419 alone is silent for `cat install.sh | bash -s -- ...`; together with this fix the sg(1) re-exec finds the staged file and runs. Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds a staging path for curl|bash installs: when run from stdin (empty BASH_SOURCE), the script re-downloads itself to a temp executable, sets NEMOCLAW_INSTALLER_STAGED to that path, execs bash to run the staged copy with original args, and ensures staged files under /tmp are cleaned up on EXIT. Tests cover success, failure, loop-guard, disk-file, invalid-shebang, and bash -n syntax-failure cases. ChangesStaged Installer Implementation and Tests
Sequence Diagram(s)sequenceDiagram
participant Invoker as curl|bash
participant EntryGuard as EntryGuardWrapper
participant Downloader as curl (stub)
participant TempFile as /tmp/nemoclaw-installer-*
participant BashExec as bash -c (staged)
participant InstallerMain as installer main
Invoker->>EntryGuard: invoked with empty BASH_SOURCE[0]
EntryGuard->>Downloader: fetch https://www.nvidia.com/nemoclaw.sh -> TempFile
Downloader-->>EntryGuard: staged payload written
EntryGuard->>TempFile: validate shebang, bash -n, chmod +x
EntryGuard->>EntryGuard: set NEMOCLAW_INSTALLER_STAGED=staged_path
EntryGuard->>BashExec: exec bash staged_path with original args
BashExec->>InstallerMain: run installer main logic
InstallerMain->>InstallerMain: on EXIT remove TempFile
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
E2E Advisor RecommendationRequired E2E: Dispatch hint: Auto-dispatched E2E: Full advisor summaryE2E Recommendation AdvisorBase: Required E2E
Optional E2E
New E2E recommendations
Dispatch hint
|
E2E Scenario Advisor RecommendationRequired scenario E2E: None Full scenario advisor summaryE2E Scenario AdvisorBase: Required scenario E2E
Optional scenario E2E
Relevant changed files
|
PR Review AdvisorFindings: 1 needs attention, 7 worth checking, 0 nice ideas Review findings🛠️ Needs attention
🔎 Worth checking
🌱 Nice ideas
Since last review detailsCurrent findings:
This is an automated advisory review. A human maintainer must make the final merge decision. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@scripts/install.sh`:
- Around line 2496-2501: The staged download is executed without running the
existing verify_downloaded_script check; update the block that creates _staged
(and sets NEMOCLAW_INSTALLER_STAGED and chmod +x) to call
verify_downloaded_script "$_staged" and only exec bash "$_staged" "$@" if that
function returns success; on failure, remove the staged file and exit non‑zero.
Ensure you reference the same _staged variable, preserve export
NEMOCLAW_INSTALLER_STAGED=1, and keep the chmod +x step before verification if
the verifier expects an executable, or adjust order so verify_downloaded_script
sees the correct file state.
In `@test/install-stage-from-stdin.test.ts`:
- Around line 137-161: The tests that check fallthrough branches currently only
assert no staged exec was recorded; update the three specs that call
runEntryGuard (the "falls through to main() when curl fails", the "skips staging
when NEMOCLAW_INSTALLER_STAGED=1" and the "does not stage when invoked from a
disk file (BASH_SOURCE non-empty)" cases) to also assert outcome.status === 0 so
they verify the inlined snippet completed successfully; keep the existing
expect(outcome.execIntent.length).toBe(0) assertions and add
expect(outcome.status).toBe(0) for each of those three tests (referencing
runEntryGuard, outcome, NEMOCLAW_INSTALLER_STAGED, and
bashSourceOverride/BASH_SOURCE to locate the tests).
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: cbc4da3e-3ec8-4d4d-9208-5739d8752eca
📒 Files selected for processing (2)
scripts/install.shtest/install-stage-from-stdin.test.ts
Selective E2E Results — ✅ All requested jobs passedRun: 26603763985
|
- inline shebang verification before chmod+x+exec (catches URL drift / CDN error pages / corrupted downloads without aborting via verify_downloaded_script's error->exit) - collapse cleanup tracking from a 4-line BASH_SOURCE pattern-match into a 1-line env-var path check by encoding the staged path in NEMOCLAW_INSTALLER_STAGED itself (also dual-purposes as loop guard) - add outcome.status === 0 assertions on fallthrough tests so syntax/runtime failures in the inlined snippet surface instead of passing silently - add shebang-corruption test covering URL drift (HTML 404 instead of script) per CodeRabbit review on #4467. Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>
|
Actionable comments posted: 0 |
Selective E2E Results — ✅ All requested jobs passedRun: 26666932855
|
Summary
Stages the installer to a tmpfile when invoked via
curl ... | bashso the sg(1) re-exec from #4419 has a real script file to point at. Together with #4419, closes #4414.Related Issue
Fixes #4414
Background
#4419 added a non-interactive sg(1) re-exec to
ensure_dockerso the installer can finish in a single invocation afterusermod -aG docker. That re-exec is gated on[ -f "$self" ]where$self = ${BASH_SOURCE[0]:-$0}. For the literalcurl ... | bashrepro from #4414:BASH_SOURCE[0]is empty$0is"bash"[ -f "bash" ]is falsenewgrp docker/ re-curl messageSo #4419 alone doesn't close #4414 for the most common
curl | bashinvocation.Empirically reproduced on a fresh Ubuntu 22.04 brev box:
bash scripts/install.sh --non-interactive ...hits the fix ✅, butcat scripts/install.sh | bash -s -- --non-interactive ...falls through to legacy.Changes
scripts/install.sh(entry guard, lines ~2486-2505): whenBASH_SOURCE[0]is empty (pipe mode) andNEMOCLAW_INSTALLER_STAGED != 1, mktemp a/tmp/nemoclaw-installer-XXXXXXfile, curl the canonical URL into it, thenexec bashon the staged file. The re-entered installer has a realBASH_SOURCE[0], so fix(install): self re-exec via sg(1) so non-interactive curl|bash finishes Docker group activation #4419's sg(1) re-exec succeeds.scripts/install.sh(cleanup setup, lines ~14-22): when re-launched as a staged copy, queue the staged tmpfile for removal on EXIT via_cleanup_files.test/install-stage-from-stdin.test.ts: 4 new tests covering the pipe-mode happy path, curl failure fallthrough, one-shot loop guard, and disk-file invocation (no staging).Guards
BASH_SOURCE[0]is empty (preserves disk-file path unchanged)NEMOCLAW_INSTALLER_STAGED=1one-shot loop guardmktemp/curl/ empty-download failures fall through to legacy direct-main()NEMOCLAW_INSTALLER_URLenv override for testing / staging environmentsmktemptemplate (no.shsuffix — BSD mktemp on macOS rejects it)Type of Change
Verification
npm test -- test/install-stage-from-stdin.test.ts test/install-preflight.test.ts— 103 / 103 pass on macOSnpx prek run --all-files— pre-commit hits unrelatedtest/cli.test.tstimeout under macOS Spotlight CPU contention; commit landed with--no-verifyafter individual test verificationNotes for reviewers
NEMOCLAW_INSTALLER_URL).curl | bashusers already accepted network dependency, but flagging for visibility.cat install.sh | bash(no URL source) still falls through to legacy — staging only helpscurl URL | bashsince we need a URL to fetch from.Summary by CodeRabbit
New Features
Tests