Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
71ad9e7
test(e2e): finish sandbox image suite migration
cv Sep 3, 2026
3ca7149
ci(images): rename sandbox image contract workflow
cv Sep 3, 2026
7e791b0
test(e2e): register managed image mock parity
cv Sep 3, 2026
378e1d9
Merge branch 'main' into refactor/finish-image-e2e-migration
cv Sep 3, 2026
976541f
test(e2e): preserve image security qualification
cv Sep 3, 2026
c29f312
test(e2e): retain fail-closed image recovery
cv Sep 3, 2026
25da558
test(e2e): simplify security helper ownership
cv Sep 3, 2026
87d6dad
test(e2e): qualify image entrypoint lifecycle
cv Sep 3, 2026
3b31472
test(e2e): close image qualification gaps
cv Sep 3, 2026
ee3d683
test(e2e): bind final image evidence
cv Sep 3, 2026
fd508f2
test(e2e): sequence protected resource cleanup
cv Sep 3, 2026
959ef7f
test(e2e): harden cleanup recovery
cv Sep 3, 2026
1172514
ci(images): consolidate final image qualification
cv Sep 3, 2026
9eea87d
Merge remote-tracking branch 'origin/main' into refactor/finish-image…
cv Sep 3, 2026
ce2fa73
test(e2e): align image proof with assertion ratchet
cv Sep 3, 2026
7094d07
test(images): retain packaged entrypoint boundaries
cv Sep 3, 2026
67a3567
test(images): close entrypoint evidence gaps
cv Sep 3, 2026
dc1d102
test(images): complete cleanup reconciliation
cv Sep 3, 2026
45f5439
test(images): preserve packaged migration contract
cv Sep 3, 2026
8aabd24
ci(images): preserve independent diagnostics
cv Sep 3, 2026
c2c0bfe
Merge branch 'main' into refactor/finish-image-e2e-migration
cv Sep 3, 2026
38d8e23
test(e2e): align deterministic parity ownership
cv Sep 3, 2026
e0bfad7
test(images): harden qualification ownership
cv Sep 3, 2026
4371d11
merge: resolve conflicts with main
github-actions[bot] Sep 3, 2026
c2a49c5
test(images): bind protected recovery evidence
cv Sep 3, 2026
e2b312e
Merge remote-tracking branch 'origin/main' into refactor/finish-image…
cv Sep 3, 2026
32b5370
Merge remote-tracking branch 'origin/main' into refactor/finish-image…
cv Sep 3, 2026
6dc872e
test(package): install registry transport as consumer
rsliter Sep 3, 2026
593d940
test(images): close local advisor findings
cv Sep 3, 2026
cd17540
test(images): retain privileged recovery proof
cv Sep 3, 2026
0f6def4
test(images): enforce reusable security consumer
cv Sep 3, 2026
64436f5
Merge remote-tracking branch 'origin/main' into refactor/finish-image…
cv Sep 3, 2026
4e24adb
test(images): type workflow mutation values
cv Sep 3, 2026
242899c
test(images): retain packaged apply proof
cv Sep 3, 2026
1aef895
test(images): bind packaged apply receipts
cv Sep 3, 2026
d835a42
Merge remote-tracking branch 'origin/main' into refactor/finish-image…
cv Sep 3, 2026
0b8dd75
Merge remote-tracking branch 'origin/main' into refactor/finish-image…
cv Sep 3, 2026
0aa81ba
Merge remote-tracking branch 'origin/main' into refactor/finish-image…
cv Sep 3, 2026
50828fe
test(e2e): reconcile live assertion ratchet
cv Sep 3, 2026
44bc61b
test(e2e): map Discord policy ratchet proof
cv Sep 3, 2026
da7b909
merge: resolve conflicts with main
github-actions[bot] Sep 3, 2026
ee130a9
test(e2e): coordinate managed security timeouts
cv Sep 3, 2026
e61acae
test(e2e): preserve external migration archive coverage
cv Sep 3, 2026
34b1461
Merge branch 'main' into refactor/finish-image-e2e-migration
cv Sep 4, 2026
0077e31
fix(ci): harden managed image artifact handoff
cv Sep 4, 2026
7a59ba7
merge: resolve PR #10941 conflicts with main
cv Sep 7, 2026
2c4049e
fix: address PR review feedback
cv Sep 8, 2026
134c55b
merge: integrate main into PR #10941
cv Sep 8, 2026
a747e2f
test: cover migration restore validation
cv Sep 8, 2026
fabde58
fix: harden migration snapshot restore
cv Sep 8, 2026
f46dfac
merge: resolve conflicts with main
github-actions[bot] Sep 8, 2026
121cea3
Merge branch 'main' into refactor/finish-image-e2e-migration
cv Sep 8, 2026
bc7e627
merge: integrate remote PR updates
cv Sep 8, 2026
f9ce7c8
fix: close migration restore races
cv Sep 8, 2026
7b1f3f9
Merge remote-tracking branch 'origin/main' into codex/pr-10941-conflicts
cv Sep 8, 2026
9ed08d2
Merge remote-tracking branch 'origin/main' into codex/pr-10941-conflicts
cv Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 30 additions & 16 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4540,6 +4540,36 @@ jobs:
"${NEMOCLAW_PROTECTED_MANAGED_IMAGE_EVIDENCE}.tmp" \
"$NEMOCLAW_PROTECTED_MANAGED_IMAGE_EVIDENCE"

- name: Validate protected managed-image evidence
shell: bash
run: >-
npx tsx tools/e2e/live-vitest-invocation.mts run --test-path test/e2e/live/managed-image-multiarch-startup.test.ts

- name: Validate OpenClaw managed-image security boundary
shell: bash
run: >-
npx tsx tools/e2e/live-vitest-invocation.mts run --test-path test/e2e/live/managed-image-openclaw-security.test.ts

- name: Validate managed-image glibc probe lifecycle
shell: bash
run: |
set -euo pipefail
export NEMOCLAW_RUN_GLIBC_PROBE_DOCKER_E2E=1
NEMOCLAW_TEST_IMAGE="$(jq -er '.[] | select(.agent == "openclaw") | .reference' "$NEMOCLAW_PROTECTED_MANAGED_IMAGE_CONTRACT")"
export NEMOCLAW_TEST_IMAGE
npx vitest run --project integration test/e2e-runtime/image-compatibility-docker-lifecycle.test.ts --silent=false --reporter=default --reporter=test/e2e/risk-signal-reporter.ts

- name: Publish exact amd64 protected runtime build cache
if: ${{ matrix.platform == 'linux/amd64' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ env.NEMOCLAW_PROTECTED_MANAGED_IMAGE_BUILD_CACHE_ARTIFACT }}
path: ${{ env.NEMOCLAW_PROTECTED_MANAGED_IMAGE_BUILD_CACHE }}/
if-no-files-found: error
retention-days: 1
compression-level: 0
overwrite: true

- name: Remove isolated protected managed-image registry
if: always()
shell: bash
Expand All @@ -4566,22 +4596,6 @@ jobs:
exit 1
fi

- name: Validate protected managed-image evidence
shell: bash
run: >-
npx tsx tools/e2e/live-vitest-invocation.mts run --test-path test/e2e/live/managed-image-multiarch-startup.test.ts

- name: Publish exact amd64 protected runtime build cache
if: ${{ matrix.platform == 'linux/amd64' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ env.NEMOCLAW_PROTECTED_MANAGED_IMAGE_BUILD_CACHE_ARTIFACT }}
path: ${{ env.NEMOCLAW_PROTECTED_MANAGED_IMAGE_BUILD_CACHE }}/
if-no-files-found: error
retention-days: 1
compression-level: 0
overwrite: true

- name: Upload protected managed-image evidence
if: always()
uses: NVIDIA/NemoClaw/.github/actions/upload-e2e-artifacts@7768e15eb90d3ee2d33432f481dfe8747e4f6d57
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ jobs:
- real-openclaw-dist-harness
- cli-tests
- plugin-tests
- sandbox-images-and-e2e
- sandbox-image-contracts
if: always()
permissions:
actions: read
Expand All @@ -366,7 +366,7 @@ jobs:
CLI_TESTS_RESULT: ${{ needs['cli-tests'].result }}
GH_TOKEN: ${{ github.token }}
PLUGIN_TESTS_RESULT: ${{ needs['plugin-tests'].result }}
SANDBOX_IMAGES_E2E_RESULT: ${{ needs['sandbox-images-and-e2e'].result }}
SANDBOX_IMAGE_CONTRACTS_RESULT: ${{ needs['sandbox-image-contracts'].result }}
RUN_ATTEMPT: ${{ github.run_attempt }}
RUN_ID: ${{ github.run_id }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
Expand Down Expand Up @@ -404,7 +404,7 @@ jobs:
local job_id=""
dependency_url="$RUN_URL"
case "$name" in
static-checks|build-typecheck|installer-integration|wechat-runtime-audit|reviewed-npm-audit|real-openclaw-dist-harness|cli-tests|plugin-tests|sandbox-images-and-e2e) ;;
static-checks|build-typecheck|installer-integration|wechat-runtime-audit|reviewed-npm-audit|real-openclaw-dist-harness|cli-tests|plugin-tests|sandbox-image-contracts) ;;
*) return ;;
esac
load_job_listing
Expand Down Expand Up @@ -447,13 +447,13 @@ jobs:
require_success "real-openclaw-dist-harness" "$REAL_OPENCLAW_DIST_HARNESS_RESULT"
require_success "cli-tests" "$CLI_TESTS_RESULT"
require_success "plugin-tests" "$PLUGIN_TESTS_RESULT"
require_success "sandbox-images-and-e2e" "$SANDBOX_IMAGES_E2E_RESULT"
require_success "sandbox-image-contracts" "$SANDBOX_IMAGE_CONTRACTS_RESULT"

[ "$failed" -eq 0 ]

sandbox-images-and-e2e:
sandbox-image-contracts:
needs: [static-checks, build-typecheck]
uses: ./.github/workflows/sandbox-images-and-e2e.yaml
uses: ./.github/workflows/sandbox-images.yaml
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
74 changes: 23 additions & 51 deletions .github/workflows/pr-self-hosted.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -204,21 +204,8 @@ jobs:
scripts/check-production-build-args.sh "${build_args[@]}"
docker build "${build_args[@]}" -t nemoclaw-production .

- name: Build sandbox test image (fixtures layered on production)
run: docker build -f test/Dockerfile.sandbox --build-arg BASE_IMAGE=nemoclaw-production -t nemoclaw-sandbox-test .

- name: Save images to tarballs
run: |
docker save nemoclaw-sandbox-test | gzip > /tmp/sandbox-test-image.tar.gz
docker save nemoclaw-production | gzip > /tmp/isolation-image.tar.gz

- name: Upload sandbox test image
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sandbox-test-image
path: /tmp/sandbox-test-image.tar.gz
retention-days: 1
if-no-files-found: error
- name: Save production image
run: docker save nemoclaw-production | gzip > /tmp/isolation-image.tar.gz
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

- name: Upload isolation image
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand Down Expand Up @@ -249,35 +236,16 @@ jobs:
scripts/check-production-build-args.sh "${build_args[@]}"
docker build "${build_args[@]}" -t nemoclaw-production-arm64 .

- name: Build sandbox test image on arm64
run: docker build -f test/Dockerfile.sandbox --build-arg BASE_IMAGE=nemoclaw-production-arm64 -t nemoclaw-sandbox-test-arm64 .

test-e2e-sandbox:
runs-on: linux-amd64-cpu4
timeout-minutes: 15
needs: build-sandbox-images
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Download image artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: sandbox-test-image
path: /tmp

- name: Load image
run: gunzip -c /tmp/sandbox-test-image.tar.gz | docker load

- name: Run sandbox E2E tests
run: docker run --rm -v "${{ github.workspace }}/test:/opt/test" nemoclaw-sandbox-test /opt/test/e2e-test.sh

test-e2e-gateway-isolation:
managed-image-openclaw-security:
runs-on: linux-amd64-cpu4
timeout-minutes: 15
timeout-minutes: 10
needs: build-sandbox-images
env:
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/managed-image-openclaw-security
E2E_TARGET_ID: managed-image-openclaw-security
NEMOCLAW_RUN_LIVE_E2E: "1"
NEMOCLAW_TEST_IMAGE: nemoclaw-production
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand All @@ -291,7 +259,7 @@ jobs:
cache: npm

- name: Install root dependencies
run: npm ci --ignore-scripts
run: npm ci --ignore-scripts --no-audit --no-fund

- name: Download image artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
Expand All @@ -300,20 +268,24 @@ jobs:
path: /tmp

- name: Load image
run: |
gunzip -c /tmp/isolation-image.tar.gz | docker load
docker image inspect nemoclaw-production >/dev/null
run: gunzip -c /tmp/isolation-image.tar.gz | docker load

- name: Validate OpenClaw managed-image security boundary
run: >-
npx tsx tools/e2e/live-vitest-invocation.mts run --test-path test/e2e/live/managed-image-openclaw-security.test.ts

- name: Run glibc probe lifecycle regression
- name: Validate glibc probe lifecycle
env:
NEMOCLAW_RUN_GLIBC_PROBE_DOCKER_E2E: "1"
NEMOCLAW_TEST_IMAGE: nemoclaw-production
run: npx vitest run --project integration test/e2e-runtime/image-compatibility-docker-lifecycle.test.ts --silent=false --reporter=default
run: >-
npx vitest run --project integration test/e2e-runtime/image-compatibility-docker-lifecycle.test.ts
--silent=false --reporter=default --reporter=test/e2e/risk-signal-reporter.ts

- name: Run gateway isolation E2E tests
run: NEMOCLAW_TEST_IMAGE=nemoclaw-production bash test/e2e-gateway-isolation.sh
- name: Upload OpenClaw managed-image security evidence
if: ${{ always() }}
uses: ./.github/actions/upload-e2e-artifacts

Comment thread
coderabbitai[bot] marked this conversation as resolved.
test-e2e-port-overrides:
port-override-image-contract:
runs-on: linux-amd64-cpu4
timeout-minutes: 10
needs: build-sandbox-images
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: Images / Build and Test Sandbox Images
name: Images / Sandbox Image Contracts

on:
# Manual dispatch is the branch-validation path. Non-main refs set
Expand Down Expand Up @@ -96,27 +96,11 @@ jobs:
scripts/check-production-build-args.sh "${build_args[@]}"
docker build "${build_args[@]}" -t nemoclaw-production .

- name: Build sandbox test image (fixtures layered on production)
run: docker build -f test/Dockerfile.sandbox --build-arg BASE_IMAGE=nemoclaw-production -t nemoclaw-sandbox-test .
- name: Save production image
run: docker save nemoclaw-production | gzip > /tmp/isolation-image.tar.gz
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

- name: Save images to tarballs
run: |
set -euo pipefail
docker save nemoclaw-sandbox-test | gzip > /tmp/sandbox-test-image.tar.gz
docker save nemoclaw-production | gzip > /tmp/isolation-image.tar.gz

- name: Verify tarballs
run: |
gzip -t /tmp/sandbox-test-image.tar.gz
gzip -t /tmp/isolation-image.tar.gz

- name: Upload sandbox test image
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sandbox-test-image
path: /tmp/sandbox-test-image.tar.gz
retention-days: 1
if-no-files-found: error
- name: Verify production image archive
run: gzip -t /tmp/isolation-image.tar.gz

- name: Upload isolation image
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand Down Expand Up @@ -438,37 +422,23 @@ jobs:
scripts/check-production-build-args.sh "${build_args[@]}"
docker build "${build_args[@]}" -t nemoclaw-production-arm64 .

- name: Build sandbox test image on arm64
run: docker build -f test/Dockerfile.sandbox --build-arg BASE_IMAGE=nemoclaw-production-arm64 -t nemoclaw-sandbox-test-arm64 .

- name: Clean up Docker auth
if: always()
shell: bash
run: bash .github/scripts/docker-auth-cleanup.sh

test-e2e-sandbox:
runs-on: ubuntu-latest
timeout-minutes: 15
needs: build-sandbox-images
steps:
- *checkout

- name: Download image artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: sandbox-test-image
path: /tmp

- name: Load image
run: gunzip -c /tmp/sandbox-test-image.tar.gz | docker load

- name: Run sandbox E2E tests
run: docker run --rm -v "${{ github.workspace }}/test:/opt/test" nemoclaw-sandbox-test /opt/test/e2e-test.sh

test-e2e-gateway-isolation:
runtime-overrides:
runs-on: ubuntu-latest
timeout-minutes: 15
# The live target owns 45 minutes; retain 15 minutes for setup, image
# transfer, and the always-running artifact upload.
timeout-minutes: 60
needs: build-sandbox-images
env:
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/runtime-overrides
E2E_TARGET_ID: runtime-overrides
NEMOCLAW_RUN_LIVE_E2E: "1"
NEMOCLAW_TEST_IMAGE: nemoclaw-production
steps:
- *checkout

Expand All @@ -490,49 +460,46 @@ jobs:
gunzip -c /tmp/isolation-image.tar.gz | docker load
docker image inspect nemoclaw-production >/dev/null

- name: Run glibc probe lifecycle regression
env:
NEMOCLAW_RUN_GLIBC_PROBE_DOCKER_E2E: "1"
NEMOCLAW_TEST_IMAGE: nemoclaw-production
run: npx vitest run --project integration test/e2e-runtime/image-compatibility-docker-lifecycle.test.ts --silent=false --reporter=default
- name: Run runtime overrides test against production image
timeout-minutes: 45
run: |
npx vitest run --project e2e-live \
test/e2e/live/runtime-overrides.test.ts \
--silent=false --reporter=default

- name: Run gateway isolation E2E tests
run: NEMOCLAW_TEST_IMAGE=nemoclaw-production bash test/e2e-gateway-isolation.sh
- name: Upload runtime overrides artifacts
if: always()
uses: ./.github/actions/upload-e2e-artifacts

runtime-overrides:
glibc-probe-image-contract:
runs-on: ubuntu-latest
# The live target owns 45 minutes; retain 15 minutes for setup, image
# transfer, and the always-running artifact upload.
timeout-minutes: 60
timeout-minutes: 10
needs: build-sandbox-images
env:
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/runtime-overrides
E2E_TARGET_ID: runtime-overrides
NEMOCLAW_RUN_LIVE_E2E: "1"
NEMOCLAW_TEST_IMAGE: nemoclaw-production
steps:
- *checkout

- *setup-node
- name: Set up Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22.19.0
cache: npm

- *install-root-dependencies
- name: Install root dependencies
run: npm ci --ignore-scripts --no-audit --no-fund

- *download-isolation-image

- *load-isolation-image

- name: Run runtime overrides test against production image
timeout-minutes: 45
run: |
npx vitest run --project e2e-live \
test/e2e/live/runtime-overrides.test.ts \
--silent=false --reporter=default

- name: Upload runtime overrides artifacts
if: always()
uses: ./.github/actions/upload-e2e-artifacts
- name: Validate glibc probe lifecycle
env:
NEMOCLAW_RUN_GLIBC_PROBE_DOCKER_E2E: "1"
NEMOCLAW_TEST_IMAGE: nemoclaw-production
run: >-
npx vitest run --project integration test/e2e-runtime/image-compatibility-docker-lifecycle.test.ts
--silent=false --reporter=default --reporter=test/e2e/risk-signal-reporter.ts

test-e2e-port-overrides:
port-override-image-contract:
runs-on: ubuntu-latest
timeout-minutes: 10
needs: build-sandbox-images
Expand All @@ -543,5 +510,5 @@ jobs:

- *load-isolation-image

- name: Run port override E2E tests
- name: Validate port override image contract
run: NEMOCLAW_TEST_IMAGE=nemoclaw-production bash test/e2e-port-overrides.sh
Loading
Loading