fix(cli): stop the packaged gateway service on final sandbox destroy - #7907
Conversation
Signed-off-by: Tinson Lai <tinsonl@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 (4)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughFinal sandbox cleanup now stops packaged OpenShell gateway services before host process reaping. The change adds platform-specific stop handling, failure propagation, tests for packaged and standalone gateways, CLI coverage, and updated operational documentation. ChangesGateway cleanup
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
Code Coverage OverviewLanguages: TypeScript TypeScript / code-coverage/pluginThe overall coverage in commit e73701b in the TypeScript / code-coverage/cliThe overall coverage in commit e73701b in the Show a code coverage summary of the most impacted files.
Updated |
|
🌿 Preview your docs: https://nvidia-preview-pr-7907.docs.buildwithfern.com/nemoclaw |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@docs/reference/troubleshooting.mdx`:
- Line 996: Update the troubleshooting heading “Gateway port stays bound after
destroying the last sandbox” to title case: “Gateway Port Stays Bound After
Destroying the Last Sandbox”.
- Around line 1009-1013: Update the Linux service-stop example in the
troubleshooting documentation to include the package-install command using
openshell-gateway, alongside the existing nemoclaw-openshell-gateway tarball
command.
In `@src/lib/onboard/docker-driver-gateway-service.ts`:
- Around line 688-691: Update the stop flow around runStopService to call
validateSystemdServiceIdentity for systemd services before issuing the stop
command, validating both FragmentPath and ExecStart. If identity validation
fails, return the existing failed-stop result without invoking systemctl stop,
while preserving the homebrew path and successful-stop behavior; add a test
covering a mismatched unit identity.
In `@test/cli/destroy-gateway-cleanup.test.ts`:
- Around line 393-395: Update the systemctlOutput assertion in the cleanup test
to require the exact unit name nemoclaw-openshell-gateway after the --user stop
arguments, while preserving the existing check that disable is not invoked.
🪄 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: e801f7d4-f408-4318-994c-cdd0bbac2299
📒 Files selected for processing (7)
docs/reference/commands.mdxdocs/reference/troubleshooting.mdxsrc/lib/actions/sandbox/destroy-gateway.test.tssrc/lib/actions/sandbox/destroy-gateway.tssrc/lib/onboard/docker-driver-gateway-service.test.tssrc/lib/onboard/docker-driver-gateway-service.tstest/cli/destroy-gateway-cleanup.test.ts
PR Review Advisor — No blocking findings reportedAdvisor assessment: No blocking advisor findings reported Model lanes
Nemotron output stays in workflow artifacts and does not change the assessment above. E2E guidanceAdvisory only. E2E / PR Gate selects and runs jobs independently. Recommended E2E: 1 optional E2E recommendation
1 warning · 0 suggestionsWarningsWarnings do not block.
|
The destroy CLI test now pins the XDG config and bin paths so the unit lookup stays inside the test home instead of following an ambient XDG_CONFIG_HOME. Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
cjagwani
left a comment
There was a problem hiding this comment.
Approved on exact head e73701b. The accepted #7904 bug scope is implemented with fail-closed packaged-service identity validation before stop, targeted regression coverage, all 54 current checks green, and the trusted onboard-repair/onboard-resume E2E plan successful. GitHub reports MERGEABLE; the checker’s only failure is base currency, covered by the maintainer stale-base waiver.
<!-- markdownlint-disable MD041 --> ## Summary Adds the canonical dated changelog entry for `v0.0.100` so the maintainer release plan can verify the pre-tag documentation prerequisite. The entry summarizes the user-facing changes merged since `v0.0.99` and links to the relevant guides. ## Changes - Add `docs/changelog/2026-07-31.mdx` with the exact `## v0.0.100` heading. - Cover restored OpenClaw pairing, transactional replacement, Deep Agents Code, onboarding recovery, lifecycle cleanup, Hermes builds, host provenance, documentation, and trusted E2E evidence. - Distinguish active Docker and Kubernetes runtime-bundle enforcement from the still-inactive managed shared-state transaction foundation. ## Source Coverage The release entry maps the doc-impacting merged PRs in the `v0.0.99..main` release range to `docs/changelog/2026-07-31.mdx`: #8021, #8024, #7973, #8028, #7947, #7788, #7884, #8023, #7969, #8020, #7989, #8000, #7907, #7942, #7567, #8013, #7955, #8017, #8014, #8015, #7629, #7644, #7821, #7971, and #7991. PR #7974 was reviewed after the final rebase and excluded because it changes internal maintainer-skill attribution policy and tests only; it does not change a user-facing product or documentation surface. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [ ] Tests added or updated for changed behavior - [x] Existing tests cover changed behavior — justification: the changelog contract test validates the dated entry, version heading, SPDX form, and route constraints. - [ ] Tests not applicable — justification: - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Documentation Writer Review - [x] Documentation writer subagent reviewed the completed changes - Result: `docs-updated` - Evidence: `docs/changelog/2026-07-31.mdx`; exact-head review passed for `6093f44f`; writing rules and documentation style reviewed; `npx vitest run test/changelog-docs.test.ts` passed 6/6; `npm run docs` passed with zero Fern errors and two generic Fern upgrade notices. - Agent: Codex Desktop <!-- docs-review-head-sha: 6093f44 --> <!-- docs-review-agents-blob-sha: 3dd7c24 --> ## DGX Station Hardware Evidence - [ ] Tested on DGX Station - Tested commit: Not applicable; no DGX Station host script changed. - Station profile/scenario: Not applicable. - Result: Not applicable. - Supporting evidence: Not applicable. ## Verification - [x] PR description includes a `Signed-off-by:` line and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run validate:pr` passed after refreshing `origin/main` when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: `npx vitest run test/changelog-docs.test.ts` passed 6/6 at `6093f44f`. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: Not applicable to a dated prose-only release entry. - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) — validation passed with zero errors; Fern emitted two generic upgrade notices. - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) — the changelog entry has the required parser-safe MDX SPDX header; dated changelog entries intentionally do not use page frontmatter. --- Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes for v0.0.100. * Documented improvements to restore pairing, sandbox replacement, onboarding recovery, lifecycle cleanup, runtime handling, build support, host readiness, and end-to-end validation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
<!-- markdownlint-disable MD041 --> ## Summary Final sandbox cleanup failed on headless Linux runners when the packaged OpenShell service existed but `systemctl --user` could not reach a user manager. Cleanup now permits the standalone path only for the recognized unavailable-manager condition and only when the packaged unit cannot activate automatically. It requires PID-bound gateway identity, verifies that the port is free, and preserves runtime evidence until cleanup completes. ## Related Issue Follow-up to #7904 and #7907. ## Changes - Classify only recognized systemd user-manager availability failures as eligible for standalone cleanup. - Refuse the fallback when the repository-managed systemd unit remains enabled for automatic activation. - Stop only the PID-file-owned gateway process after exact gateway name and port validation. - Require a successful host bind probe before gateway registration and shared-volume cleanup. - Preserve PID and runtime-marker evidence across partial cleanup failures and retries. - Keep host process, port, and runtime-file operations in the host-gateway adapter boundary. - Document the narrow headless Linux behavior in the `destroy` command reference. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [x] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [x] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [ ] Tests not applicable — justification: - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [x] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [x] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: Independent Codex Desktop security review PASS on exact head `c14826163d08d98031a583c49407783355b24592` against base `227e8b92b600c77684fe45befd7909ae4ad39141`; all nine categories passed with no actionable findings. - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Documentation Writer Review - [x] Documentation writer subagent reviewed the completed changes - Result: `docs-updated` - Evidence: Reviewed `docs/reference/commands.mdx` and every changed comment, diagnostic, and test title against the implementation, writing rules, controlled word list, and documentation contributor guide. The final test-only delta keeps the injected cleanup failure path linear and preserves its exact marker-path assertion. `npm run docs` completed with 0 errors and 2 generic Fern upgrade notices. - Agent: Codex Desktop <!-- docs-review-head-sha: c148261 --> <!-- docs-review-agents-blob-sha: 3dd7c24 --> ## DGX Station Hardware Evidence - [ ] Tested on DGX Station - Tested commit: - Station profile/scenario: - Result: - Supporting evidence: ## Verification - [x] PR description includes a `Signed-off-by:` line and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run validate:pr` passed after refreshing `origin/main` when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — `npx vitest run --project cli src/lib/actions/sandbox/destroy-gateway.test.ts src/lib/onboard/docker-driver-gateway-service.test.ts src/lib/onboard/host-gateway-process.test.ts` (62 passed); `npm run typecheck:cli` passed. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) Exact local evidence: head `c14826163d08d98031a583c49407783355b24592`; base `227e8b92b600c77684fe45befd7909ae4ad39141`; complete seven-file diff reviewed; `git diff --check` passed; diff-aware `pre-commit`, `commit-msg`, and `pre-push` stages passed against `upstream/main`. Product scope: approved independently of GitHub merge state. This fixes the accepted final-destroy behavior from #7904 and the packaged-service lifecycle established by #7907. It adds no new integration, configuration surface, image, third-party stack, or supported workflow. --- Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved headless Linux cleanup when the system service manager is unavailable. * Verifies gateway ownership and port release before removing gateway resources. * Prevents cleanup when process ownership or port availability cannot be confirmed. * Preserves prior failure behavior for other service-stop errors. * **Tests** * Added coverage for fallback cleanup, ownership validation, occupied ports, retry behavior, and runtime-file handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
Summary
Final-sandbox gateway cleanup branched only on whether the gateway is externally supervised, so a gateway owned by the packaged OpenShell gateway service reached the PID-file reaper instead, and that reaper had nothing to stop because a healthy managed-service start clears the PID file. Destroy therefore reported success while the service manager kept the gateway port bound. Cleanup now stops the packaged service before it reaps host processes, and refuses to continue when the service survives.
Related Issue
Fixes #7904
Changes
src/lib/onboard/docker-driver-gateway-service.ts:stopOpenShellGatewayUserServicestops the resolved gateway service through the same manager the start path uses,systemctl --user stoporbrew services stop. The command the start path already ran inline moves into a sharedrunStopService, so start behaviour is unchanged. The stop reportsattempted: falsewhen no service is installed or the platform has no service manager, so a caller can fall through to its existing teardown instead of failing. Covered bydocker-driver-gateway-service.test.ts.src/lib/actions/sandbox/destroy-gateway.ts:cleanupGatewayAfterLastSandboxstops the packaged service when the resolved owner namespackaged-serviceas its source, before the PID-file reaper. The service is stopped, not disabled or removed, because destroy is not uninstall and the next onboarding run starts it again. A stop that was attempted and failed throws with the service status command and aborts before gateway registration and volume removal, matching the existing surviving-listener refusal. A standalone or externally supervised gateway takes the previous paths untouched. Covered bydestroy-gateway.test.tsandtest/cli/destroy-gateway-cleanup.test.ts.docs/reference/commands.mdx,docs/reference/troubleshooting.mdx: document the service stop in thedestroyreference, and add the remediation for a gateway port that stays bound after the final destroy.Type of Change
Quality Gates
Documentation Writer Review
blockeddocs/reference/commands.mdx,docs/reference/troubleshooting.mdx; the review is blocked because no documentation writer subagent was available in the authoring session.DGX Station Hardware Evidence
Verification
Signed-off-by:line and every commit appears asVerifiedin GitHubpre-commit,commit-msg, andpre-pushhooks passed, ornpm run validate:prpassed after refreshingorigin/mainwhen hooks were skipped or unavailablenpx vitest run --project cli src/lib/actions/sandbox/destroy-gateway.test.ts src/lib/onboard/docker-driver-gateway-service.test.ts— 40 passed.npx vitest run --project integration test/cli/destroy-gateway-cleanup.test.ts— 12 passed.npx vitest run --project integration test/destroy-wipe-sandbox-state.test.ts test/gateway-final-failure-cleanup.test.ts— 26 passed.npx vitest run --project cli src/lib/actions/sandbox src/lib/onboard --maxWorkers=4— 545 of 546 files passed;src/lib/onboard/docker-driver-gateway-jwt-bundle.test.tsfails the same way on an unmodified checkout of this base.npm run typecheck:cli,npx biome check, andnpm run checks:repositoryare clean.npm run docsreports 0 errors and 2 warnings, both pre-existing accent-colour contrast warnings from the shared theme configuration rather than the changed pages.npm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — command/result:npm run docsbuilds without warnings (doc changes only)Signed-off-by: Tinson Lai tinsonl@nvidia.com
Summary by CodeRabbit
Bug Fixes
destroy --cleanup-gatewayso that when the packaged OpenShell gateway is systemd-managed, the gateway service is stopped before host-process reaping—freeing the gateway port for later onboarding.destroynow exits non-zero after sandbox/registry deletion, prints the service status command, and skips gateway and volume removal.Documentation
destroyand Troubleshooting guidance for packaged OpenShell gateway cleanup and Linux remediation, including consistent headings and an explicitsystemctl --user stop openshell-gatewaycommand for package installs.