fix: revert base image digest pinning that broke all e2e tests#1938
Conversation
) The digest from blueprint.yaml (openshell-community registry) was applied to the nemoclaw/sandbox-base registry, causing "manifest unknown" on every sandbox creation. Reverts cf4941a until digest pinning can use the correct registry/digest pair. Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
📝 WalkthroughWalkthroughThe PR removes sandbox upgrade behaviors: the post-install "upgrade-sandboxes" invocation, blueprint base-image digest extraction and digest-pinned pre-pull, and the global CLI Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 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)
Comment |
Run shfmt and Prettier on files that diverged from formatter output. Update test regex to handle multi-line runOpenshell call after Prettier. Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
There was a problem hiding this comment.
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)
src/lib/onboard.ts (1)
983-1073:⚠️ Potential issue | 🟠 MajorKeep a base-image upgrade signal in the sandbox path.
This revert fixes the bad repo-specific digest, but it also removes the only mechanism in this file that forced sandboxes onto the current
sandbox-base. The reuse path here still keeps a ready sandbox indefinitely, and the rebuild path no longer pins or refreshes the base image before build. After a NemoClaw upgrade, users can therefore remain on an older OpenClaw either by reuse or by rebuilding from a locally cached base tag, which is the regression issue#1904was trying to solve.Please keep a repo-correct freshness check here before release — e.g. resolve the digest from
ghcr.io/nvidia/nemoclaw/sandbox-base, or force a pull /--pull-equivalent before the sandbox build.Also applies to: 2506-2556, 2574-2796
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard.ts` around lines 983 - 1073, The revert removed the mechanism that enforces sandbox base-image freshness, causing sandboxes to stick to stale sandbox-base digests; in patchStagedDockerfile restore a repo-correct upgrade signal by resolving the current digest for ghcr.io/nvidia/nemoclaw/sandbox-base (or otherwise fetching the manifest) and inject it into the staged Dockerfile (e.g. as ARG NEMOCLAW_SANDBOX_BASE_DIGEST or NEMOCLAW_BASE_DIGEST) or ensure the sandbox build uses a forced pull (equivalent to docker build --pull) so rebuilt sandboxes get the latest sandbox-base; update patchStagedDockerfile (and any callers that rely on encodeDockerJsonArg / getSandboxInferenceConfig) to write that digest/flag into the dockerfile content or into the sandbox path so reuse and rebuild paths both honor base-image refresh.
🧹 Nitpick comments (1)
src/nemoclaw.ts (1)
1605-1608: SplitsandboxRebuildinto smaller steps to reduce complexity.This function is still too branch-heavy for safe iteration/debugging, and this PR touches it. Extracting step helpers (precheck, backup, delete, recreate, restore, post-migrate) would materially improve maintainability and reduce regression risk.
As per coding guidelines, "Limit cyclomatic complexity to 20 in JavaScript/TypeScript files, with target of 15".
Also applies to: 1655-1657, 1670-1672, 1692-1694, 1711-1713, 1723-1725, 1736-1741, 1758-1760, 1770-1772, 1779-1781, 1785-1787, 1809-1811
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/nemoclaw.ts` around lines 1605 - 1608, The sandboxRebuild function is too branch-heavy; refactor it into clear step helpers to reduce cyclomatic complexity and improve maintainability—extract and call small functions such as sandboxPrecheck, sandboxBackup, sandboxDelete, sandboxRecreate, sandboxRestore, and sandboxPostMigrate from within sandboxRebuild, move the corresponding branching and try/catch logic into these helpers, preserve existing error handling and return behavior (including verbose flag handling via the verbose const), and update any callers/tests to use the refactored flow so behavior remains identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/nemoclaw.ts`:
- Around line 2033-2035: The CLI no longer recognizes the removed command
"upgrade-sandboxes", which causes generic unknown-command errors; update the CLI
command dispatch (where commands are registered/handled—the code that prints the
Backup help block and resolves input commands) to detect the legacy literal
"upgrade-sandboxes" and provide a deterministic migration path: either print a
clear deprecation/migration message directing users to "nemoclaw backup-all" and
exit with a non-zero status, or implement a compatibility shim that logs a
deprecation warning and forwards the invocation to the existing "backup-all"
handler; make sure to reference "upgrade-sandboxes" and the existing
"backup-all" handler when adding this logic.
---
Outside diff comments:
In `@src/lib/onboard.ts`:
- Around line 983-1073: The revert removed the mechanism that enforces sandbox
base-image freshness, causing sandboxes to stick to stale sandbox-base digests;
in patchStagedDockerfile restore a repo-correct upgrade signal by resolving the
current digest for ghcr.io/nvidia/nemoclaw/sandbox-base (or otherwise fetching
the manifest) and inject it into the staged Dockerfile (e.g. as ARG
NEMOCLAW_SANDBOX_BASE_DIGEST or NEMOCLAW_BASE_DIGEST) or ensure the sandbox
build uses a forced pull (equivalent to docker build --pull) so rebuilt
sandboxes get the latest sandbox-base; update patchStagedDockerfile (and any
callers that rely on encodeDockerJsonArg / getSandboxInferenceConfig) to write
that digest/flag into the dockerfile content or into the sandbox path so reuse
and rebuild paths both honor base-image refresh.
---
Nitpick comments:
In `@src/nemoclaw.ts`:
- Around line 1605-1608: The sandboxRebuild function is too branch-heavy;
refactor it into clear step helpers to reduce cyclomatic complexity and improve
maintainability—extract and call small functions such as sandboxPrecheck,
sandboxBackup, sandboxDelete, sandboxRecreate, sandboxRestore, and
sandboxPostMigrate from within sandboxRebuild, move the corresponding branching
and try/catch logic into these helpers, preserve existing error handling and
return behavior (including verbose flag handling via the verbose const), and
update any callers/tests to use the refactored flow so behavior remains
identical.
🪄 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 Plus
Run ID: b3d7c9f0-65a7-4e75-970a-73124f72d34d
📒 Files selected for processing (4)
scripts/brev-launchable-ci-cpu.shsrc/lib/onboard.tssrc/nemoclaw.tstest/onboard.test.ts
✅ Files skipped from review due to trivial changes (1)
- scripts/brev-launchable-ci-cpu.sh
🚧 Files skipped from review as they are similar to previous changes (1)
- test/onboard.test.ts
| ${G}Backup:${R} | ||
| nemoclaw backup-all Back up all sandbox state before upgrade | ||
| nemoclaw upgrade-sandboxes Detect and rebuild stale sandboxes ${D}(--check, --auto)${R} | ||
|
|
There was a problem hiding this comment.
Add an explicit migration note for removed upgrade-sandboxes command.
Given the command surface changed, consider a dedicated deprecation/error path so old scripts/users get a deterministic migration hint instead of generic unknown-command behavior.
Suggested compatibility shim
+ if (cmd === "upgrade-sandboxes") {
+ console.error(" `nemoclaw upgrade-sandboxes` has been removed.");
+ console.error(" Use `nemoclaw backup-all` before upgrade, then `nemoclaw <name> rebuild` per sandbox.");
+ process.exit(1);
+ }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/nemoclaw.ts` around lines 2033 - 2035, The CLI no longer recognizes the
removed command "upgrade-sandboxes", which causes generic unknown-command
errors; update the CLI command dispatch (where commands are
registered/handled—the code that prints the Backup help block and resolves input
commands) to detect the legacy literal "upgrade-sandboxes" and provide a
deterministic migration path: either print a clear deprecation/migration message
directing users to "nemoclaw backup-all" and exit with a non-zero status, or
implement a compatibility shim that logs a deprecation warning and forwards the
invocation to the existing "backup-all" handler; make sure to reference
"upgrade-sandboxes" and the existing "backup-all" handler when adding this
logic.
…sandboxes (#1904) Re-implements the digest pinning and upgrade-sandboxes features reverted in #1938. The original PR (#1937) broke all e2e tests because it read a digest from blueprint.yaml (belongs to ghcr.io/nvidia/openshell-community) and applied it to ghcr.io/nvidia/nemoclaw/sandbox-base — a different registry. Docker digests are repo-specific, so every pull returned "manifest unknown". This fix never reads blueprint.yaml for the base image digest. Instead: - pullAndResolveBaseImageDigest() pulls sandbox-base:latest from GHCR - docker inspect extracts the actual repo digest - patchStagedDockerfile() pins ARG BASE_IMAGE to the inspected digest The digest is self-consistent by construction — it always comes from the same registry we pin to. Falls back to unpinned :latest when GHCR is unreachable (offline/firewall users). Also re-adds the upgrade-sandboxes command with fixes from code review: - --auto flag for non-interactive installer contexts - sandbox list failure handling before classifying sandboxes - throwOnError option for sandboxRebuild to prevent process.exit in loops Closes #1904 Signed-off-by: Test User <test@example.com>
…sandboxes (#1904) Re-implements the digest pinning and upgrade-sandboxes features reverted in #1938. The original PR (#1937) broke all e2e tests because it read a digest from blueprint.yaml (belongs to ghcr.io/nvidia/openshell-community) and applied it to ghcr.io/nvidia/nemoclaw/sandbox-base — a different registry. Docker digests are repo-specific, so every pull returned "manifest unknown". This fix never reads blueprint.yaml for the base image digest. Instead: - pullAndResolveBaseImageDigest() pulls sandbox-base:latest from GHCR - docker inspect extracts the actual repo digest - patchStagedDockerfile() pins ARG BASE_IMAGE to the inspected digest The digest is self-consistent by construction — it always comes from the same registry we pin to. Falls back to unpinned :latest when GHCR is unreachable (offline/firewall users). Also re-adds the upgrade-sandboxes command with fixes from code review: - --auto flag for non-interactive installer contexts - sandbox list failure handling before classifying sandboxes - throwOnError option for sandboxRebuild to prevent process.exit in loops Closes #1904 Signed-off-by: Test User <test@example.com> Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
…sandboxes (#1904) Re-implements the digest pinning and upgrade-sandboxes features reverted in #1938. The original PR (#1937) broke all e2e tests because it read a digest from blueprint.yaml (belongs to ghcr.io/nvidia/openshell-community) and applied it to ghcr.io/nvidia/nemoclaw/sandbox-base — a different registry. Docker digests are repo-specific, so every pull returned "manifest unknown". This fix never reads blueprint.yaml for the base image digest. Instead: - pullAndResolveBaseImageDigest() pulls sandbox-base:latest from GHCR - docker inspect extracts the actual repo digest - patchStagedDockerfile() pins ARG BASE_IMAGE to the inspected digest The digest is self-consistent by construction — it always comes from the same registry we pin to. Falls back to unpinned :latest when GHCR is unreachable (offline/firewall users). Also re-adds the upgrade-sandboxes command with fixes from code review: - --auto flag for non-interactive installer contexts - sandbox list failure handling before classifying sandboxes - throwOnError option for sandboxRebuild to prevent process.exit in loops - RepoDigests filtered by SANDBOX_BASE_IMAGE prefix (ordering not guaranteed) - Exit non-zero from upgrade-sandboxes when sandbox list or rebuilds fail - Report sandboxes with unavailable version detection Closes #1904 Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
…sandboxes (#1943) ## Summary - Re-implements digest pinning and `upgrade-sandboxes` reverted in #1938 - Fixes the root cause: original PR read a digest from `blueprint.yaml` (belongs to `ghcr.io/nvidia/openshell-community`) and applied it to `ghcr.io/nvidia/nemoclaw/sandbox-base` — a different registry. Docker digests are repo-specific, so every sandbox creation failed with "manifest unknown" - New approach: `pullAndResolveBaseImageDigest()` pulls `sandbox-base:latest` from GHCR, then `docker inspect` extracts the actual repo digest. The digest is self-consistent by construction — it always comes from the same registry we pin to - Falls back to unpinned `:latest` when GHCR is unreachable (offline/firewall users) - Re-adds `nemoclaw upgrade-sandboxes` command with `--check`/`--auto`/`--yes` flags and fixes from CodeRabbit review (sandbox list error handling, `throwOnError` for batch rebuilds, `--auto` in install.sh) Closes #1904 ## Test plan - [x] 8 new unit tests (6 in onboard.test.ts, 2 CLI integration tests in cli.test.ts) - [x] Regression guard: verifies `ARG BASE_IMAGE` references `nemoclaw/sandbox-base`, NOT `openshell-community` - [x] Structural test: `pullAndResolveBaseImageDigest()` called before `patchStagedDockerfile()` - [x] CLI test: `upgrade-sandboxes --check` detects stale sandbox (original reporter scenario from #1904) - [x] CLI test: `upgrade-sandboxes --check` reports all-current when no sandboxes are stale - [x] Nightly cloud e2e: verify sandbox creation succeeds with digest pinning (the exact scenario that broke in #1937) - [ ] Manual: verify `nemoclaw upgrade-sandboxes --check` on a real environment with a stale sandbox <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a CLI command to detect and batch-upgrade stale sandboxes (report-only and auto/yes modes). * Installer now performs a post-onboarding scan and can trigger non-blocking sandbox upgrades. * **Improvements** * Sandbox base images are pinned to resolved digests when available for more reproducible builds. * Rebuild flow updated to continue processing multiple sandboxes and surface per-sandbox failures without aborting the whole run. * **Tests** * New unit/integration and end-to-end tests covering detection, reporting, upgrade, and rebuild workflows. * **Chores** * Nightly workflow extended with new E2E jobs; CI failure artifacts and notifications updated. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Summary
blueprint.yamlbelongs toghcr.io/nvidia/openshell-community/sandboxes/openclawbut the code applied it toghcr.io/nvidia/nemoclaw/sandbox-base— a different registry repoWhat's removed
getBlueprintBaseImageDigest()function and DockerfileBASE_IMAGEpatching inonboard.tsnemoclaw upgrade-sandboxescommand innemoclaw.tsinstall.shonboard.test.tsTest plan
Closes #1904 (will need to be re-opened with the correct registry approach)
Signed-off-by: Aaron Erickson aerickson@nvidia.com
Summary by CodeRabbit
Refactor
Tests