ci(images): publish validated managed OCI images - #7756
Conversation
📝 WalkthroughWalkthroughThe PR adds contract-based managed-image publication for three agents across two architectures, including immutable builds, validation, aggregate promotion barriers, alias verification, artifact retention, and reviewed path-glob expansion. ChangesManaged image publication
Estimated code review effort: 5 (Critical) | ~90+ minutes Sequence Diagram(s)sequenceDiagram
participant BaseImageWorkflow
participant ManagedImagesWorkflow
participant GHCR
BaseImageWorkflow->>ManagedImagesWorkflow: provide managed-base contract artifacts
ManagedImagesWorkflow->>GHCR: build and push digest-only images
ManagedImagesWorkflow->>ManagedImagesWorkflow: validate six candidate contracts
ManagedImagesWorkflow->>GHCR: stage cohort aliases
ManagedImagesWorkflow->>GHCR: publish verified OpenClaw aliases
Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
Code Coverage OverviewLanguages: TypeScript TypeScript / code-coverage/pluginThe overall coverage in commit 061e44f in the TypeScript / code-coverage/cliThe overall coverage in commit 061e44f in the Show a code coverage summary of the most impacted files.
Updated |
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: This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge. |
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com> # Conflicts: # .github/workflows/base-image.yaml
Preserve the reviewed managed-image publication patch. Incorporate current main after PR #7747 merged. Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Preserve the validated six-file publication slice. Incorporate the exact current main head. Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Preserve the validated six-file publication slice. Incorporate the exact latest main head. Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Preserve the validated six-file publication slice. Stage the latest main head after current evidence completes. Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
There was a problem hiding this comment.
🧹 Nitpick comments (6)
.github/workflows/base-image.yaml (2)
549-609: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftThree byte-identical contract blocks differ only by agent name.
The ~60-line contract generation plus
jq -einvariant block is copied verbatim for Hermes, Deep Agents Code, and OpenClaw, withagent:and the error string as the only deltas. A single composite action (or a matrixed manifest job keyed on agent/image) would keep the invariant list from drifting per agent.Also applies to: 731-791, 915-975
🤖 Prompt for 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. In @.github/workflows/base-image.yaml around lines 549 - 609, Consolidate the duplicated contract generation and validation blocks used by the Hermes, Deep Agents Code, and OpenClaw sections into one reusable composite action or matrix-driven manifest flow. Parameterize the agent, image, and related output values, while preserving the shared contract schema and jq invariants exactly; remove the three independently maintained copies.
536-547: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winUse
--formatforimagetools inspectdigests Replace thesedscrape of theDigest:line withdocker buildx imagetools inspect --format '{{.Manifest.Digest}}'in the threebase-image.yamlpublish blocks and themanaged-images.yamlcohort-alias block; keep the existingcmpcheck.🤖 Prompt for 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. In @.github/workflows/base-image.yaml around lines 536 - 547, Replace the sed-based Digest scraping in the publish block at .github/workflows/base-image.yaml lines 536-547 and the cohort-alias block at .github/workflows/managed-images.yaml lines 738-747 with docker buildx imagetools inspect --format '{{.Manifest.Digest}}'. Preserve the existing single-digest validation, reference construction, and cmp check; apply the same format-based digest retrieval to all three base-image.yaml publish blocks.test/e2e/support/base-image-publication.test.ts (1)
267-288: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAsserting the full
gitargv locks in incidental flag ordering.The behaviors that matter are the
:(glob)pathspec magic and first-parent scoping;--format=/--name-onlyorder is incidental and will break this test on any harmless refactor. Consider asserting the invariants instead (each call contains--first-parent, ends with the expected:(glob)pathspec, and targetsEXPECTED_SHA).As per path instructions, "Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call assertions."
🤖 Prompt for 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. In `@test/e2e/support/base-image-publication.test.ts` around lines 267 - 288, Update the assertions around the git calls in the base-image publication test to verify observable invariants rather than the complete argv ordering: each call must include --first-parent, target EXPECTED_SHA, and end with the expected :(glob) pathspec for agents or src/lib/messaging. Remove dependence on incidental --format=/--name-only ordering while preserving validation of both expected pathspecs.Source: Path instructions
test/managed-image-publication-workflow.test.ts (2)
137-156: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMarker lists assert workflow source text rather than behavior.
validationMarkersand the jq-fragment substring checks pin exact shell/jq text, so any harmless rewording of the workflow scripts fails these tests even though the guarantees still hold. TherunPublicationBarrier/runManagedImagePromotiontests below already prove the barrier and promotion behavior by executing the extracted scripts; consider trimming the string markers to the few that cannot be executed (e.g.provenance/sbominputs) and leaning on the executed-script tests for the rest.As per path instructions, "Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call assertions."
Also applies to: 183-193
🤖 Prompt for 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. In `@test/managed-image-publication-workflow.test.ts` around lines 137 - 156, Trim validationMarkers and forbiddenPerLanePromotionMarkers in the workflow publication tests to only non-executable guarantees that cannot be covered behaviorally, such as provenance or SBOM inputs. Remove redundant exact shell/jq substring assertions for behavior already exercised by runPublicationBarrier and runManagedImagePromotion, while preserving those executed-script tests as the source of truth.Source: Path instructions
646-650: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
displayAgentternary has identical branches.Both arms return
agent, so the variable is dead indirection — useagentdirectly.♻️ Proposed cleanup
- const displayAgent = - agent === "langchain-deepagents-code" ? "langchain-deepagents-code" : agent; return { - name: `managed-image-${displayAgent}-${artifactPlatform}`, + name: `managed-image-${agent}-${artifactPlatform}`,🤖 Prompt for 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. In `@test/managed-image-publication-workflow.test.ts` around lines 646 - 650, Remove the redundant displayAgent variable in the managed image publication workflow test and use agent directly when constructing the name and path fields in the returned object. Preserve the existing output values and artifact path structure.tools/e2e/base-image-publication.mts (1)
242-291: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy liftFull-history glob expansion is unbounded and then splatted into a single
gitargv.
git log --name-only <sha> -- :(glob)agents/**enumerates every path ever touched under the glob across the whole first-parent history (not just paths present atexpectedSha). Foragents/**,scripts/**, andsrc/lib/messaging/**that can be many thousands of entries, all of which are then spread into onegit loginvocation at Line 323 — slow, and at risk of exceeding the argv limit as history grows.Since
gitalready accepts pathspec magic, the expansion is avoidable: pass:(glob)<path>for reviewed globs and literals otherwise directly to the relevant-commit query, keeping the validation you have for the returned SHA. If you keep expansion for evidence purposes, bound it withgit ls-tree -r --name-only <sha> -- :(glob)<path>(paths at the tip) instead of full history.🤖 Prompt for 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. In `@tools/e2e/base-image-publication.mts` around lines 242 - 291, Update expandBaseImagePushPaths to avoid enumerating full first-parent history for reviewed globs. Pass each reviewed path as a Git pathspec directly to the relevant-commit query, while retaining literal handling for non-glob paths and the existing returned-SHA/path validation. If expansion remains necessary, use tip-only ls-tree results for expectedSha rather than git log history.
🤖 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.
Nitpick comments:
In @.github/workflows/base-image.yaml:
- Around line 549-609: Consolidate the duplicated contract generation and
validation blocks used by the Hermes, Deep Agents Code, and OpenClaw sections
into one reusable composite action or matrix-driven manifest flow. Parameterize
the agent, image, and related output values, while preserving the shared
contract schema and jq invariants exactly; remove the three independently
maintained copies.
- Around line 536-547: Replace the sed-based Digest scraping in the publish
block at .github/workflows/base-image.yaml lines 536-547 and the cohort-alias
block at .github/workflows/managed-images.yaml lines 738-747 with docker buildx
imagetools inspect --format '{{.Manifest.Digest}}'. Preserve the existing
single-digest validation, reference construction, and cmp check; apply the same
format-based digest retrieval to all three base-image.yaml publish blocks.
In `@test/e2e/support/base-image-publication.test.ts`:
- Around line 267-288: Update the assertions around the git calls in the
base-image publication test to verify observable invariants rather than the
complete argv ordering: each call must include --first-parent, target
EXPECTED_SHA, and end with the expected :(glob) pathspec for agents or
src/lib/messaging. Remove dependence on incidental --format=/--name-only
ordering while preserving validation of both expected pathspecs.
In `@test/managed-image-publication-workflow.test.ts`:
- Around line 137-156: Trim validationMarkers and
forbiddenPerLanePromotionMarkers in the workflow publication tests to only
non-executable guarantees that cannot be covered behaviorally, such as
provenance or SBOM inputs. Remove redundant exact shell/jq substring assertions
for behavior already exercised by runPublicationBarrier and
runManagedImagePromotion, while preserving those executed-script tests as the
source of truth.
- Around line 646-650: Remove the redundant displayAgent variable in the managed
image publication workflow test and use agent directly when constructing the
name and path fields in the returned object. Preserve the existing output values
and artifact path structure.
In `@tools/e2e/base-image-publication.mts`:
- Around line 242-291: Update expandBaseImagePushPaths to avoid enumerating full
first-parent history for reviewed globs. Pass each reviewed path as a Git
pathspec directly to the relevant-commit query, while retaining literal handling
for non-glob paths and the existing returned-SHA/path validation. If expansion
remains necessary, use tip-only ls-tree results for expectedSha rather than git
log history.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 5cc1220e-6e4c-447f-b4ec-1371c7f73a90
📒 Files selected for processing (6)
.github/workflows/base-image.yaml.github/workflows/managed-images.yamltest/e2e/support/base-image-publication.test.tstest/helpers/managed-image-publication-barrier.tstest/managed-image-publication-workflow.test.tstools/e2e/base-image-publication.mts
Preserve the validated six-file publication slice. Incorporate the exact current main head. Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
<!-- markdownlint-disable MD041 --> ## Summary Adds the canonical July 30 release entry for `v0.0.99` before the release tag is captured. The entry covers all 37 merged PRs since `v0.0.98` and bounds experimental or dormant work without presenting it as supported behavior. ## Changes - Adds `docs/changelog/2026-07-30.mdx` with the exact `## v0.0.99` heading, parser-safe MDX SPDX comment, summary, detailed release bullets, and published documentation routes. - Records user-visible recovery, snapshot, shared-route, Hermes, readiness, inference, image, documentation, and release E2E changes. - States that the managed-image selection and startup-profile contracts remain dormant and do not activate buildless onboarding. Source summary: - [#7972](#7972) -> `docs/changelog/2026-07-30.mdx`: Records restored managed OpenClaw configuration modes during recovery. - [#7834](#7834) -> `docs/changelog/2026-07-30.mdx`: Records clone-bound pairing verification after snapshot restore. - [#7975](#7975) -> `docs/changelog/2026-07-30.mdx`: Records managed startup recovery coverage. - [#7960](#7960) -> `docs/changelog/2026-07-30.mdx`: Records dormant startup-profile coordination without activating a supported surface. - [#7856](#7856) -> `docs/changelog/2026-07-30.mdx`: Records persistence of the credential-free OpenClaw startup command. - [#7959](#7959) -> `docs/changelog/2026-07-30.mdx`: Records dormant startup-profile construction without changing onboarding. - [#7946](#7946) -> `docs/changelog/2026-07-30.mdx`: Records the internal startup-profile schema and transport contract. - [#7951](#7951) -> `docs/changelog/2026-07-30.mdx`: Records platform-pull cleanup before managed-image validation. - [#7949](#7949) -> `docs/changelog/2026-07-30.mdx`: Records rejection of retained Hermes `uv` build cache metadata. - [#7597](#7597) -> `docs/changelog/2026-07-30.mdx`: Records separate command and agent first-turn latency evidence. - [#7931](#7931) -> `docs/changelog/2026-07-30.mdx`: Records focused E2E replacement evidence for retired selectors. - [#7950](#7950) -> `docs/changelog/2026-07-30.mdx`: Records exclusion of build-only BuildKit telemetry from the Deep Agents Code probe. - [#7665](#7665) -> `docs/changelog/2026-07-30.mdx`: Records consolidated priority 2 E2E coverage. - [#7911](#7911) -> `docs/changelog/2026-07-30.mdx`: Records the corrected NVIDIA DORI installation pin. - [#7934](#7934) -> `docs/changelog/2026-07-30.mdx`: Records the staging image-family wait before Brev Launchable deployment. - [#7772](#7772) -> `docs/changelog/2026-07-30.mdx`: Records dormant managed-image selection contracts without activating buildless onboarding. - [#7941](#7941) -> `docs/changelog/2026-07-30.mdx`: Records corrected agent-specific provider and policy guidance. - [#7819](#7819) -> `docs/changelog/2026-07-30.mdx`: Records removal of empty Deep Agents Code provider-switch sections. - [#7932](#7932) -> `docs/changelog/2026-07-30.mdx`: Records independent credential-generation E2E execution. - [#7840](#7840) -> `docs/changelog/2026-07-30.mdx`: Records shared-route preservation and pre-delete peer validation during upgrades. - [#7874](#7874) -> `docs/changelog/2026-07-30.mdx`: Records the split between pre-tag release entries and post-tag Announcements. - [#7876](#7876) -> `docs/changelog/2026-07-30.mdx`: Records the writable Hermes runtime root within lockdown. - [#7756](#7756) -> `docs/changelog/2026-07-30.mdx`: Records validated multi-platform managed-image publication. - [#7914](#7914) -> `docs/changelog/2026-07-30.mdx`: Records accepted `uv` version metadata in Hermes image validation. - [#7686](#7686) -> `docs/changelog/2026-07-30.mdx`: Records the explicitly experimental Microsoft Entra runtime identity reference. - [#7869](#7869) -> `docs/changelog/2026-07-30.mdx`: Records classified gateway relaunch quarantine and rebuild guidance. - [#7814](#7814) -> `docs/changelog/2026-07-30.mdx`: Records state restore into replacement sandboxes and SQLite write verification. - [#7839](#7839) -> `docs/changelog/2026-07-30.mdx`: Records quieter onboarding test execution without a user-facing behavior claim. - [#7854](#7854) -> `docs/changelog/2026-07-30.mdx`: Records generalized agent-selection guidance. - [#7845](#7845) -> `docs/changelog/2026-07-30.mdx`: Records isolated CDI test evidence without a user-facing behavior claim. - [#7843](#7843) -> `docs/changelog/2026-07-30.mdx`: Records the corrected Omni sub-agent model ID. - [#7908](#7908) -> `docs/changelog/2026-07-30.mdx`: Records reviewed Hermes and Deep Agents Code dependency pins. - [#7887](#7887) -> `docs/changelog/2026-07-30.mdx`: Records rejection of a symlinked DGX Station release marker. - [#7747](#7747) -> `docs/changelog/2026-07-30.mdx`: Records the internal compute-driver separation without a user-facing behavior claim. - [#7660](#7660) -> `docs/changelog/2026-07-30.mdx`: Records atomic publication of rebuild recovery manifests. - [#7661](#7661) -> `docs/changelog/2026-07-30.mdx`: Records bounded local inference health-response retention. - [#7654](#7654) -> `docs/changelog/2026-07-30.mdx`: Records state preservation across supervisor relaunch recovery. ## 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: `test/changelog-docs.test.ts` validates the dated changelog contract, SPDX comment, version heading, and published routes. - [ ] 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-30.mdx`; the documentation-only diff passed review against `WRITING.md`, the controlled word list, and `docs/CONTRIBUTING.md`. The review covered terminology, structure, active voice, release meaning, product-scope boundaries, and link and code presentation. Changelog tests passed 6/6, and the docs build reported 0 errors with 2 pre-existing warnings. - Agent: Codex CLI <!-- docs-review-head-sha: 200940f --> <!-- docs-review-agents-blob-sha: c052d60 --> ## 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 — command/result or justification: `npx vitest run test/changelog-docs.test.ts` passed 6/6 tests. - [ ] 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 this documentation-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) — result: Build passed with 0 errors and 2 pre-existing warnings. - [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) --- Signed-off-by: San Dang <sdang@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes for v0.0.99 covering snapshot restoration, sandbox recovery, gateway route upgrades, and Hermes security updates. * Documented experimental Microsoft Entra runtime identity support and enhanced readiness checks. * Added details on managed image validation, trusted CI image promotion, and end-to-end release evidence. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
Publish runnable, agent-complete OCI images from trusted CI so later onboarding can consume immutable digests without building Dockerfiles on the user host. The publisher keeps image construction in the existing reviewed Dockerfiles, binds every final image to the exact base digest produced in the same workflow run, and validates the public runtime contract before creating consumer aliases. This is stack PR 2 for #7744.
Related Issue
Related to #7744
Changes
linux/amd64managed images with SBOM and maximum provenance attestations.Type of Change
Quality Gates
Documentation Writer Review
no-docs-needed061e44f571db, this slice only publishes internal managed-image artifacts and validation contracts. It does not activate CLI or runtime selection, and existing Dockerfile-based onboarding documentation remains accurate until a later slice consumes these images. The exact-head review also replaced an ambiguous test title with the explicit release-tag non-cancellation invariant.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/mainnpx vitest run --project integration test/managed-image-publication-workflow.test.tsandnpx vitest run --project e2e-support test/e2e/support/base-image-publication.test.tspassed 46 tests on the refreshed stack head.npm run validate:pralso passed.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: Aaron Erickson aerickson@nvidia.com