Skip to content

fix(install): pin OpenShell to 0.0.22, upgrade on mismatch#1459

Open
ericksoa wants to merge 5 commits intomainfrom
fix/pin-openshell-version
Open

fix(install): pin OpenShell to 0.0.22, upgrade on mismatch#1459
ericksoa wants to merge 5 commits intomainfrom
fix/pin-openshell-version

Conversation

@ericksoa
Copy link
Copy Markdown
Contributor

@ericksoa ericksoa commented Apr 3, 2026

Summary

  • Adds openshellVersion: "0.0.22" to package.json as single source of truth for the required OpenShell CLI version
  • install-openshell.sh now reads OPENSHELL_PIN_VERSION env var to download that exact tagged release (not latest) and treats it as the minimum required version
  • onboard.js compares the installed OpenShell version against the pin and triggers an upgrade when below — previously it only checked binary presence

Test plan

  • npm test passes (new tests for versionGte and install script pin awareness)
  • Fresh install on machine without OpenShell installs v0.0.22 specifically
  • Upgrade from OpenShell 0.0.21 triggers upgrade to 0.0.22
  • Machine with OpenShell 0.0.22+ skips install
  • Standalone install-openshell.sh (no env var) still downloads latest and uses 0.0.22 floor

Fixes NVBug 6044568

Summary by CodeRabbit

  • New Features

    • Added OpenShell version pinning support via a package metadata field (default 0.0.22) and made installer respect a pinned version when present.
    • Improved install/preflight behavior to detect installed OpenShell version and install/upgrade when below the required pinned version.
  • Tests

    • Added unit and regression tests for version comparison and pinned-release download behavior.

Upgrading NemoClaw did not upgrade OpenShell because (1) onboard.js
only checked binary presence, not version, and (2) install-openshell.sh
had a hardcoded MIN_VERSION floor of 0.0.7 and always downloaded the
latest release.

Add openshellVersion pin to package.json as single source of truth.
The install script now reads OPENSHELL_PIN_VERSION env var to download
that exact tagged release and treat it as the minimum required version.
Onboard compares the installed version against the pin and triggers an
upgrade when the installed version is too old.

Fixes: NVBug 6044568
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

📝 Walkthrough

Walkthrough

Added a semver comparison helper versionGte() and exported it. Onboard logic now reads openshellVersion from package.json, uses it to decide install/upgrade via versionGte(), and passes a pinned version via OPENSHELL_PIN_VERSION to the install script. Installer script conditionally downloads a pinned release (or falls back to latest).

Changes

Cohort / File(s) Summary
Onboard library
bin/lib/onboard.js
Added and exported versionGte(left, right) that compares major.minor.patch strings (non-numeric segments parsed as 0). installOpenshell() reads openshellVersion from ../../package.json, sets OPENSHELL_PIN_VERSION on a cloned env, and uses that env in spawnSync. preflight() computes installed OpenShell version and uses versionGte to decide install vs. upgrade, with distinct log messages for missing vs. below-required versions.
Package metadata
package.json
Added top-level openshellVersion: "0.0.22".
Installer script
scripts/install-openshell.sh
Replaced hard-coded MIN_VERSION with REQUIRED_VERSION="${OPENSHELL_PIN_VERSION:-0.0.22}". When OPENSHELL_PIN_VERSION is set, download commands use --tag "v${OPENSHELL_PIN_VERSION}" for gh and releases/download/v${OPENSHELL_PIN_VERSION} for curl; otherwise retain latest behavior.
Tests
test/onboard.test.js, test/runner.test.js
Added unit test for versionGte() semver comparisons. Added regression test asserting scripts/install-openshell.sh contains OPENSHELL_PIN_VERSION, REQUIRED_VERSION, --tag "v${OPENSHELL_PIN_VERSION}", and curl URL path with download/v${OPENSHELL_PIN_VERSION}.

Sequence Diagram

sequenceDiagram
    participant PkgJson as package.json
    participant Onboard as bin/lib/onboard.js
    participant InstallScript as scripts/install-openshell.sh
    participant GitHub as GitHub Releases

    Onboard->>PkgJson: Read openshellVersion
    PkgJson-->>Onboard: "0.0.22"
    Onboard->>Onboard: getInstalledOpenshellVersion()
    Onboard->>Onboard: versionGte(installed, pinned)?
    alt missing or version < pinned
        Onboard->>InstallScript: spawnSync with env (OPENSHELL_PIN_VERSION=0.0.22)
        InstallScript->>GitHub: gh release download --tag v0.0.22 / curl .../releases/download/v0.0.22/...
        GitHub-->>InstallScript: Release artifact
        InstallScript-->>Onboard: Installation complete
    else version sufficient
        Onboard-->>Onboard: Skip installation
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I hopped through versions, sniffed 0.0.22,
I learned to count dots and zeros too,
I pass the pin along the shelly trail,
No more guessing if installs will fail,
A rabbit’s nod—our releases set true.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: pinning OpenShell to a specific version (0.0.22) and upgrading when there's a version mismatch. This matches the core functionality introduced across all modified files.

✏️ 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/pin-openshell-version

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

@ericksoa ericksoa self-assigned this Apr 3, 2026
@ericksoa ericksoa closed this Apr 4, 2026
@ericksoa
Copy link
Copy Markdown
Contributor Author

ericksoa commented Apr 4, 2026

No longer relev

@ericksoa ericksoa reopened this Apr 4, 2026
ericksoa added 2 commits April 3, 2026 19:06
…sion

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>

# Conflicts:
#	scripts/install-openshell.sh
@ericksoa ericksoa changed the title fix(install): pin OpenShell to 0.0.21, upgrade on mismatch fix(install): pin OpenShell to 0.0.22, upgrade on mismatch Apr 4, 2026
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: 1

🧹 Nitpick comments (1)
bin/lib/onboard.js (1)

2070-2084: Extract the OpenShell gate into a helper to keep preflight() complexity under control.

This block is functionally good, but it adds more branching inside an already complex function. Consider moving this logic to a dedicated helper and reusing a single cached openshellVersion constant.

♻️ Suggested refactor
+const { openshellVersion: OPEN_SHELL_PIN_VERSION } = require("../../package.json");
+
+function getOpenshellInstallDecision(installedVersion, pinnedVersion = OPEN_SHELL_PIN_VERSION) {
+  const needsInstall =
+    !installedVersion || (pinnedVersion && !versionGte(installedVersion, pinnedVersion));
+  return { needsInstall, pinnedVersion };
+}
+
 function installOpenshell() {
-  const pinnedVersion = require("../../package.json").openshellVersion;
+  const pinnedVersion = OPEN_SHELL_PIN_VERSION;
   const installEnv = { ...process.env };
   if (pinnedVersion) {
     installEnv.OPENSHELL_PIN_VERSION = pinnedVersion;
   }
   ...
 }
 
 // inside preflight()
-  const pinnedOpenshellVersion = require("../../package.json").openshellVersion;
   let openshellInstall = { localBin: null, futureShellPathHint: null };
   const installedOpenshellVersion = isOpenshellInstalled() ? getInstalledOpenshellVersion() : null;
-  const needsInstall =
-    !installedOpenshellVersion ||
-    (pinnedOpenshellVersion && !versionGte(installedOpenshellVersion, pinnedOpenshellVersion));
+  const { needsInstall, pinnedVersion: pinnedOpenshellVersion } =
+    getOpenshellInstallDecision(installedOpenshellVersion);

As per coding guidelines, "Enforce cyclomatic complexity limit of 20 (ratcheting down to 15) via ESLint".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/lib/onboard.js` around lines 2070 - 2084, Extract the OpenShell
install/upgrade gate out of preflight() into a new helper e.g.
ensureOpenshellPresent(), moving the logic that reads pinnedOpenshellVersion,
checks isOpenshellInstalled(), calls getInstalledOpenshellVersion(), computes
needsInstall with versionGte(), and returns the openshellInstall object
(localBin/futureShellPathHint) and installed/pinned versions; replace the
inlined block in preflight() with a single call to ensureOpenshellPresent() and
use a single cached constant for pinnedOpenshellVersion (read once) to avoid
repeated file reads and reduce cyclomatic complexity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/install-openshell.sh`:
- Around line 88-95: Add a validation step for OPENSHELL_PIN_VERSION before
using it: check OPENSHELL_PIN_VERSION against a strict semver regex (e.g.,
major.minor.patch with optional pre-release/build) and if it fails print a clear
error via info or echo and exit non‑zero; only then set GH_TAG_FLAG and
CURL_TAG_PATH and log "Pinned to OpenShell v${OPENSHELL_PIN_VERSION}". Update
the branch that assigns GH_TAG_FLAG, CURL_TAG_PATH and the info message
(references: GH_TAG_FLAG, CURL_TAG_PATH, OPENSHELL_PIN_VERSION) to perform this
guard so malformed values won't reach the download/checksum stages.

---

Nitpick comments:
In `@bin/lib/onboard.js`:
- Around line 2070-2084: Extract the OpenShell install/upgrade gate out of
preflight() into a new helper e.g. ensureOpenshellPresent(), moving the logic
that reads pinnedOpenshellVersion, checks isOpenshellInstalled(), calls
getInstalledOpenshellVersion(), computes needsInstall with versionGte(), and
returns the openshellInstall object (localBin/futureShellPathHint) and
installed/pinned versions; replace the inlined block in preflight() with a
single call to ensureOpenshellPresent() and use a single cached constant for
pinnedOpenshellVersion (read once) to avoid repeated file reads and reduce
cyclomatic complexity.
🪄 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: Pro

Run ID: f2bd867e-2044-498a-bbd2-84eed0544134

📥 Commits

Reviewing files that changed from the base of the PR and between b403a0b and a063b21.

📒 Files selected for processing (4)
  • bin/lib/onboard.js
  • package.json
  • scripts/install-openshell.sh
  • test/onboard.test.js
✅ Files skipped from review due to trivial changes (2)
  • package.json
  • test/onboard.test.js

Comment on lines +88 to +95
# When a pin is set, download that exact tag; otherwise download latest.
GH_TAG_FLAG=()
CURL_TAG_PATH="latest/download"
if [[ -n "${OPENSHELL_PIN_VERSION:-}" ]]; then
GH_TAG_FLAG=(--tag "v${OPENSHELL_PIN_VERSION}")
CURL_TAG_PATH="download/v${OPENSHELL_PIN_VERSION}"
info "Pinned to OpenShell v${OPENSHELL_PIN_VERSION}"
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Validate OPENSHELL_PIN_VERSION format before using it.

If the env var is malformed, the script fails later during download/checksum with less actionable errors. Add an early semver-format guard for better reliability.

🛡️ Suggested hardening
 if [[ -n "${OPENSHELL_PIN_VERSION:-}" ]]; then
+  if [[ ! "${OPENSHELL_PIN_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+    fail "Invalid OPENSHELL_PIN_VERSION '${OPENSHELL_PIN_VERSION}' (expected X.Y.Z)"
+  fi
   GH_TAG_FLAG=(--tag "v${OPENSHELL_PIN_VERSION}")
   CURL_TAG_PATH="download/v${OPENSHELL_PIN_VERSION}"
   info "Pinned to OpenShell v${OPENSHELL_PIN_VERSION}"
 fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# When a pin is set, download that exact tag; otherwise download latest.
GH_TAG_FLAG=()
CURL_TAG_PATH="latest/download"
if [[ -n "${OPENSHELL_PIN_VERSION:-}" ]]; then
GH_TAG_FLAG=(--tag "v${OPENSHELL_PIN_VERSION}")
CURL_TAG_PATH="download/v${OPENSHELL_PIN_VERSION}"
info "Pinned to OpenShell v${OPENSHELL_PIN_VERSION}"
fi
# When a pin is set, download that exact tag; otherwise download latest.
GH_TAG_FLAG=()
CURL_TAG_PATH="latest/download"
if [[ -n "${OPENSHELL_PIN_VERSION:-}" ]]; then
if [[ ! "${OPENSHELL_PIN_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
fail "Invalid OPENSHELL_PIN_VERSION '${OPENSHELL_PIN_VERSION}' (expected X.Y.Z)"
fi
GH_TAG_FLAG=(--tag "v${OPENSHELL_PIN_VERSION}")
CURL_TAG_PATH="download/v${OPENSHELL_PIN_VERSION}"
info "Pinned to OpenShell v${OPENSHELL_PIN_VERSION}"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/install-openshell.sh` around lines 88 - 95, Add a validation step for
OPENSHELL_PIN_VERSION before using it: check OPENSHELL_PIN_VERSION against a
strict semver regex (e.g., major.minor.patch with optional pre-release/build)
and if it fails print a clear error via info or echo and exit non‑zero; only
then set GH_TAG_FLAG and CURL_TAG_PATH and log "Pinned to OpenShell
v${OPENSHELL_PIN_VERSION}". Update the branch that assigns GH_TAG_FLAG,
CURL_TAG_PATH and the info message (references: GH_TAG_FLAG, CURL_TAG_PATH,
OPENSHELL_PIN_VERSION) to perform this guard so malformed values won't reach the
download/checksum stages.

@wscurran wscurran added Getting Started Use this label to identify setup, installation, or onboarding issues. priority: high Important issue that should be resolved in the next release NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). OpenShell Support for OpenShell, a safe, private runtime for autonomous AI agents fix labels Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Getting Started Use this label to identify setup, installation, or onboarding issues. NemoClaw CLI Use this label to identify issues with the NemoClaw command-line interface (CLI). OpenShell Support for OpenShell, a safe, private runtime for autonomous AI agents priority: high Important issue that should be resolved in the next release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants