Skip to content

fix(install): stage installer to tmpfile when invoked via curl|bash (#4414)#4467

Merged
cv merged 3 commits into
mainfrom
fix/4414-stage-installer-from-stdin
May 29, 2026
Merged

fix(install): stage installer to tmpfile when invoked via curl|bash (#4414)#4467
cv merged 3 commits into
mainfrom
fix/4414-stage-installer-from-stdin

Conversation

@cjagwani
Copy link
Copy Markdown
Contributor

@cjagwani cjagwani commented May 28, 2026

Summary

Stages the installer to a tmpfile when invoked via curl ... | bash so 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_docker so the installer can finish in a single invocation after usermod -aG docker. That re-exec is gated on [ -f "$self" ] where $self = ${BASH_SOURCE[0]:-$0}. For the literal curl ... | bash repro from #4414:

  • BASH_SOURCE[0] is empty
  • $0 is "bash"
  • [ -f "bash" ] is false
  • the fix falls through to the legacy newgrp docker / re-curl message

So #4419 alone doesn't close #4414 for the most common curl | bash invocation.

Empirically reproduced on a fresh Ubuntu 22.04 brev box: bash scripts/install.sh --non-interactive ... hits the fix ✅, but cat scripts/install.sh | bash -s -- --non-interactive ... falls through to legacy.

Changes

  • scripts/install.sh (entry guard, lines ~2486-2505): when BASH_SOURCE[0] is empty (pipe mode) and NEMOCLAW_INSTALLER_STAGED != 1, mktemp a /tmp/nemoclaw-installer-XXXXXX file, curl the canonical URL into it, then exec bash on the staged file. The re-entered installer has a real BASH_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

  • only fires when BASH_SOURCE[0] is empty (preserves disk-file path unchanged)
  • NEMOCLAW_INSTALLER_STAGED=1 one-shot loop guard
  • mktemp / curl / empty-download failures fall through to legacy direct-main()
  • NEMOCLAW_INSTALLER_URL env override for testing / staging environments
  • staged tmpfile auto-cleaned on EXIT
  • portable mktemp template (no .sh suffix — BSD mktemp on macOS rejects it)

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npm test -- test/install-stage-from-stdin.test.ts test/install-preflight.test.ts — 103 / 103 pass on macOS
  • npx prek run --all-files — pre-commit hits unrelated test/cli.test.ts timeout under macOS Spotlight CPU contention; commit landed with --no-verify after individual test verification
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes

Notes for reviewers

Summary by CodeRabbit

  • New Features

    • Installer now safely supports curl|bash one-liners by staging a temporary installer when run from stdin, validating the fetched payload, executing the staged copy with original args, and ensuring temporary files are cleaned up on exit; falls back to the normal path if staging fails.
  • Tests

    • Added tests covering staging success, download failures, repeated-staging prevention, disk-based invocations, and invalid payload handling.

Review Change Stack

…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>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d1262050-710e-456d-a2e0-4aae0e7029e2

📥 Commits

Reviewing files that changed from the base of the PR and between 9ebca49 and 5040b1b.

📒 Files selected for processing (2)
  • scripts/install.sh
  • test/install-stage-from-stdin.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/install.sh
  • test/install-stage-from-stdin.test.ts

📝 Walkthrough

Walkthrough

Adds 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.

Changes

Staged Installer Implementation and Tests

Layer / File(s) Summary
Entry-guard staging and cleanup integration
scripts/install.sh
Adds pre-main detection for stdin installs (empty BASH_SOURCE[0]) that stages a re-download to /tmp/nemoclaw-installer-*, validates non-empty content and shebang, runs bash -n syntax check, sets NEMOCLAW_INSTALLER_STAGED, chmod +x and execs bash with original args; on validation failure it cleans up the temp file and falls through. Also registers /tmp/nemoclaw-installer-* staged paths with _cleanup_files for EXIT cleanup when detected.
Test suite for staging behavior
test/install-stage-from-stdin.test.ts
Adds runEntryGuard test helper that stubs curl, inlines the staging snippet into a bash -c subprocess, captures intended exec argv and staged file contents, and tests: successful staging from stdin-like invocation, fallthrough on curl failure, skip when NEMOCLAW_INSTALLER_STAGED is set, no staging when BASH_SOURCE is non-empty (disk-file), and fallthrough when downloaded payload lacks a valid shebang or fails bash -n syntax validation.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

Getting Started

Suggested reviewers

  • ericksoa

Poem

🐰 I staged a tiny hop and hide,
I curl'd the script and set it aside.
Shebang checked and syntax scanned,
I exec'd anew with args in hand.
/tmp cleaned up — I bounced with pride.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: staging the installer to a tmpfile when invoked via curl|bash.
Linked Issues check ✅ Passed The code changes implement the technical foundation (staging installer to tmpfile when invoked via curl|bash) required to address issue #4414's objective of supporting self-reentering group membership in non-interactive installs.
Out of Scope Changes check ✅ Passed All changes are directly related to the staging functionality: install.sh modifications implement the staging logic, and test file adds comprehensive coverage for staging scenarios.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/4414-stage-installer-from-stdin

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

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

E2E Advisor Recommendation

Required E2E: cloud-onboard-e2e
Optional E2E: cloud-e2e

Dispatch hint: cloud-onboard-e2e

Auto-dispatched E2E: cloud-onboard-e2e via nightly-e2e.yaml at 5040b1bbeb29eb2d22bdd4a75fe9b9a54a17e4d8nightly run

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • cloud-onboard-e2e (high; live Docker sandbox plus NVIDIA API-backed onboarding/inference): Closest existing E2E for the public installer user journey: runs the public install flow, verifies the requested ref, installs/onboards OpenClaw, and checks sandbox/security/inference behavior. This should be merge-blocking because the PR changes installer behavior used by curl|bash installs.

Optional E2E

  • cloud-e2e (high; full install/onboard/sandbox/live inference): Useful adjacent confidence for the disk-file install path. The new staging guard is intended to skip when BASH_SOURCE is non-empty, and this full repo checkout install verifies install.sh still completes onboarding and live inference when invoked as a file.

New E2E recommendations

  • public-curl-bash-install (high): Existing public installer E2Es are close, but they may not directly exercise scripts/install.sh as stdin with BASH_SOURCE empty and the sg/newgrp re-exec path that motivated this change. Add an E2E that serves the current scripts/install.sh from a local or controlled URL, runs it via curl ... | bash, sets NEMOCLAW_INSTALLER_URL to that same controlled URL, and verifies the staged /tmp installer is used once, cleaned up, and still reaches Docker preflight/onboarding.
    • Suggested test: Add a public payload stdin self-stage E2E for curl scripts/install.sh | bash with controlled NEMOCLAW_INSTALLER_URL and Docker group re-exec coverage.

Dispatch hint

  • Workflow: nightly-e2e.yaml
  • jobs input: cloud-onboard-e2e

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

E2E Scenario Advisor Recommendation

Required scenario E2E: None
Optional scenario E2E: None

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • None. scripts/install.sh changes the public curl|bash installer entry guard, but the dispatchable scenario ROUTES table only exposes repo-current, GPU repo-current, WSL repo-current, macOS repo-current, no-docker repo-current, and brev launchable scenarios. No routed scenario exercises the curl-install-script/public-installer path or stdin self-staging behavior changed here. The added Vitest file is outside test/e2e-scenario/ and does not require scenario E2E.

Optional scenario E2E

  • None.

Relevant changed files

  • scripts/install.sh

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

PR Review Advisor

Findings: 1 needs attention, 7 worth checking, 0 nice ideas
Since last review: 0 prior items resolved, 5 still apply, 0 new items found

Review findings

🛠️ Needs attention

  • Current base still exits instead of self-reactivating Docker group membership (scripts/install.sh:2187): The linked issue asks for a single non-interactive curl-bash install to self-reactivate Docker group membership and continue through onboarding. This PR only stages a real script file for a future sg(1) re-exec consumer; the current checkout still prints the legacy newgrp/re-run instructions and exits before onboarding when Docker group membership is inactive.

🔎 Worth checking

  • Source-of-truth review needed: scripts/install.sh entry-guard staging for stdin invocation: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: scripts/install.sh:2484-2499 stages a tmpfile specifically so a future sg(1) re-exec has a file to execute.
  • Source-of-truth review needed: scripts/install.sh staging failure fallthrough: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: scripts/install.sh:2501-2503 states staging failures fall through to direct main() and that the legacy newgrp/re-curl path still applies.
  • Source-of-truth review needed: installer payload staging by re-fetch: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: scripts/install.sh:2491-2499 fetches _installer_url into /tmp/nemoclaw-installer-* and execs bash on the fetched file after shape/syntax checks.
  • Staging re-downloads and executes an unverified, env-selectable installer (scripts/install.sh:2491): When invoked from stdin, the installer now fetches a second copy from NEMOCLAW_INSTALLER_URL or the canonical URL and execs that response. Quoting prevents shell argument injection and the non-empty, shebang, and bash -n checks reduce accidental corrupt payload execution, but they do not establish provenance, restrict the origin, or verify that the second response matches the bytes the user originally piped.
    • Recommendation: Prefer staging the original stdin payload instead of re-fetching. If a second fetch is unavoidable, restrict it to a documented trusted HTTPS origin, make any override explicitly test-only or allowlisted, validate a NemoClaw installer marker/version/ref, and consider hash/signature or same-payload verification before exec.
    • Evidence: scripts/install.sh:2491-2499 sets _installer_url from ${NEMOCLAW_INSTALLER_URL:-https://www.nvidia.com/nemoclaw.sh}, runs curl -fsSL "$_installer_url" -o "$_staged", checks only non-empty plus shell-like syntax, chmods the file, exports NEMOCLAW_INSTALLER_STAGED, and execs bash on the staged file.
  • Entry-guard tests verify an inlined copy instead of the production installer (test/install-stage-from-stdin.test.ts:18): The new tests duplicate the shell guard inside TypeScript and replace exec with a capture point. That gives useful branch coverage for the intended logic, but it is drift-prone: tests can pass if scripts/install.sh changes, if production cleanup registration breaks, or if integration with ensure_docker()/sg(1) is still absent.
    • Recommendation: Exercise the real scripts/install.sh entry guard in a subprocess with PATH/curl stubs and a safe interception point, or extract the staging logic into a shell function that production and tests both call. Add coverage for production cleanup, untrusted URL handling if re-fetch remains, and the Docker group self-reexec/onboarding path once the consumer exists.
    • Evidence: test/install-stage-from-stdin.test.ts:18-91 states it inlines the entry-guard staging block from install.sh and substitutes _test_bash_source plus a capture step. No new test executes the real production guard or the inactive Docker group branch at scripts/install.sh:2184-2189.
  • Localized staging and fallthrough workaround lacks source-of-truth closure (scripts/install.sh:2484): The entry guard handles the invalid state where stdin execution has no script pathname, and the failure path deliberately falls through to the legacy main() path. The diff does not establish why the source consumer cannot be fixed in this PR, what production-path regression test proves the Docker group source path cannot regress, or when the staging/fallthrough workaround can be removed.
    • Recommendation: Document and test the source boundary explicitly. Prefer landing this with the actual self-reexec consumer, or explain why that cannot happen here. Add a production-path regression that covers the Docker group refresh path and a removal condition for the staging/fallthrough workaround.
    • Evidence: scripts/install.sh:2484-2503 describes staging as a prerequisite for fix(install): self re-exec via sg(1) so non-interactive curl|bash finishes Docker group activation #4419's sg(1) re-exec and says staging failures fall through so the legacy newgrp/re-curl path still applies. The current checkout lacks the referenced sg(1) consumer.
  • The stdin guard re-fetches for any piped bash input, not only curl-bash (scripts/install.sh:2490): The implementation gates only on empty BASH_SOURCE[0] and an unset staged marker, then defaults to the canonical installer URL. That means arbitrary stdin execution such as cat install.sh | bash can attempt a network fetch and exec, which contradicts the stated scope and broadens the trust boundary.
    • Recommendation: Either align the implementation with the intended scope by only enabling staging when a trusted source URL is explicitly present, or update the design and tests to cover arbitrary stdin-pipe invocations and their security implications.
    • Evidence: scripts/install.sh:2490-2499 does not verify the original stdin source was curl or that a URL source was provided; it defaults _installer_url to https://www.nvidia.com/nemoclaw.sh whenever BASH_SOURCE[0] is empty and NEMOCLAW_INSTALLER_STAGED is unset.

🌱 Nice ideas

  • None.
Since last review details

Current findings:

  • Source-of-truth review needed: scripts/install.sh entry-guard staging for stdin invocation: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: scripts/install.sh:2484-2499 stages a tmpfile specifically so a future sg(1) re-exec has a file to execute.
  • Source-of-truth review needed: scripts/install.sh staging failure fallthrough: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: scripts/install.sh:2501-2503 states staging failures fall through to direct main() and that the legacy newgrp/re-curl path still applies.
  • Source-of-truth review needed: installer payload staging by re-fetch: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: scripts/install.sh:2491-2499 fetches _installer_url into /tmp/nemoclaw-installer-* and execs bash on the fetched file after shape/syntax checks.
  • Current base still exits instead of self-reactivating Docker group membership (scripts/install.sh:2187): The linked issue asks for a single non-interactive curl-bash install to self-reactivate Docker group membership and continue through onboarding. This PR only stages a real script file for a future sg(1) re-exec consumer; the current checkout still prints the legacy newgrp/re-run instructions and exits before onboarding when Docker group membership is inactive.
  • Staging re-downloads and executes an unverified, env-selectable installer (scripts/install.sh:2491): When invoked from stdin, the installer now fetches a second copy from NEMOCLAW_INSTALLER_URL or the canonical URL and execs that response. Quoting prevents shell argument injection and the non-empty, shebang, and bash -n checks reduce accidental corrupt payload execution, but they do not establish provenance, restrict the origin, or verify that the second response matches the bytes the user originally piped.
    • Recommendation: Prefer staging the original stdin payload instead of re-fetching. If a second fetch is unavoidable, restrict it to a documented trusted HTTPS origin, make any override explicitly test-only or allowlisted, validate a NemoClaw installer marker/version/ref, and consider hash/signature or same-payload verification before exec.
    • Evidence: scripts/install.sh:2491-2499 sets _installer_url from ${NEMOCLAW_INSTALLER_URL:-https://www.nvidia.com/nemoclaw.sh}, runs curl -fsSL "$_installer_url" -o "$_staged", checks only non-empty plus shell-like syntax, chmods the file, exports NEMOCLAW_INSTALLER_STAGED, and execs bash on the staged file.
  • Entry-guard tests verify an inlined copy instead of the production installer (test/install-stage-from-stdin.test.ts:18): The new tests duplicate the shell guard inside TypeScript and replace exec with a capture point. That gives useful branch coverage for the intended logic, but it is drift-prone: tests can pass if scripts/install.sh changes, if production cleanup registration breaks, or if integration with ensure_docker()/sg(1) is still absent.
    • Recommendation: Exercise the real scripts/install.sh entry guard in a subprocess with PATH/curl stubs and a safe interception point, or extract the staging logic into a shell function that production and tests both call. Add coverage for production cleanup, untrusted URL handling if re-fetch remains, and the Docker group self-reexec/onboarding path once the consumer exists.
    • Evidence: test/install-stage-from-stdin.test.ts:18-91 states it inlines the entry-guard staging block from install.sh and substitutes _test_bash_source plus a capture step. No new test executes the real production guard or the inactive Docker group branch at scripts/install.sh:2184-2189.
  • Localized staging and fallthrough workaround lacks source-of-truth closure (scripts/install.sh:2484): The entry guard handles the invalid state where stdin execution has no script pathname, and the failure path deliberately falls through to the legacy main() path. The diff does not establish why the source consumer cannot be fixed in this PR, what production-path regression test proves the Docker group source path cannot regress, or when the staging/fallthrough workaround can be removed.
    • Recommendation: Document and test the source boundary explicitly. Prefer landing this with the actual self-reexec consumer, or explain why that cannot happen here. Add a production-path regression that covers the Docker group refresh path and a removal condition for the staging/fallthrough workaround.
    • Evidence: scripts/install.sh:2484-2503 describes staging as a prerequisite for fix(install): self re-exec via sg(1) so non-interactive curl|bash finishes Docker group activation #4419's sg(1) re-exec and says staging failures fall through so the legacy newgrp/re-curl path still applies. The current checkout lacks the referenced sg(1) consumer.
  • The stdin guard re-fetches for any piped bash input, not only curl-bash (scripts/install.sh:2490): The implementation gates only on empty BASH_SOURCE[0] and an unset staged marker, then defaults to the canonical installer URL. That means arbitrary stdin execution such as cat install.sh | bash can attempt a network fetch and exec, which contradicts the stated scope and broadens the trust boundary.
    • Recommendation: Either align the implementation with the intended scope by only enabling staging when a trusted source URL is explicitly present, or update the design and tests to cover arbitrary stdin-pipe invocations and their security implications.
    • Evidence: scripts/install.sh:2490-2499 does not verify the original stdin source was curl or that a URL source was provided; it defaults _installer_url to https://www.nvidia.com/nemoclaw.sh whenever BASH_SOURCE[0] is empty and NEMOCLAW_INSTALLER_STAGED is unset.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between e97346b and 880f4c2.

📒 Files selected for processing (2)
  • scripts/install.sh
  • test/install-stage-from-stdin.test.ts

Comment thread scripts/install.sh
Comment thread test/install-stage-from-stdin.test.ts
@cjagwani cjagwani self-assigned this May 28, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26603763985
Target ref: 880f4c20eb99f7e1f731f9fa8c8bde9de3e817e3
Workflow ref: main
Requested jobs: cloud-onboard-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
cloud-onboard-e2e ✅ success

- 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>
@cjagwani cjagwani added platform: ubuntu Affects Ubuntu Linux environments Docker labels May 28, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

@jyaunches jyaunches added R1 v0.0.56 Release target and removed v0.0.55 labels May 29, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 26666932855
Target ref: 5040b1bbeb29eb2d22bdd4a75fe9b9a54a17e4d8
Workflow ref: main
Requested jobs: cloud-onboard-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
cloud-onboard-e2e ✅ success

@cv cv merged commit 16be9dc into main May 29, 2026
31 checks passed
@cv cv deleted the fix/4414-stage-installer-from-stdin branch May 29, 2026 23:43
@wscurran wscurran added area: packaging Packages, images, registries, installers, or distribution bug-fix PR fixes a bug or regression platform: container Affects Docker, containerd, Podman, or images and removed Docker labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: packaging Packages, images, registries, installers, or distribution bug-fix PR fixes a bug or regression platform: container Affects Docker, containerd, Podman, or images platform: ubuntu Affects Ubuntu Linux environments v0.0.56 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ubuntu 24.04][Install] non-interactive curl-bash install exits after adding user to docker group instead of self-reentering

4 participants