Docker, image, and Helm tests
Human verified
A human reviewed this page, but it may be out of date. Later edits may not have been reviewed.
Overview
Run Compose startup, container image, and Helm checks. Use Kubernetes for an authenticated Agent journey: the Docker Compute Driver rejects Agent harness authentication bindings, so no Docker test deploys an Agent or makes a model call.
Verify Compose startup
Compose supports control-plane startup and Namespace operations.
Start the Docker Compute preview with
OCC_DEVELOPMENT_COMPUTE_DRIVER=docker ./scripts/dev-up; with no selection,
startup uses the Kubernetes-only profile. Run the startup and preflight cases:
node --test tests/integration/dev-up-compose-startup.test.ts \ tests/integration/dev-up-compose.test.mjsThe tests run the launcher and render configuration with Compose. Fixture commands stand in for engine operations such as starting services and copying the service key.
On macOS, follow the Podman prerequisite in the startup flow.
Use the cleanup command printed by dev-up to preserve the database and credentials.
Verify Compose cleanup
With Go, Podman and podman-compose installed, run:
OCC_TEST_PODMAN_COMPUTE_REAL=1 node --test --test-name-pattern='Compose cleanup preserves' \ tests/integration/docker-compute-real.test.mjsOn macOS, select the machine with CONTAINER_CONNECTION. For Docker Engine and
Compose, use OCC_TEST_DOCKER_COMPUTE_REAL=1 instead. This case uses disposable
resources and verifies that occ dev down preserves the database volume unless
--volumes is specified. It does not deploy an Agent.
Driver regressions
node --test tests/conformance/docker-compute.test.tsOCC_TEST_DOCKER_TOKEN_RETRY=1 NODE_BASE_IMAGE=node:24-bookworm \ node --test tests/integration/docker-compute-token-retry.test.tsThe first uses a local HTTP fault fixture. The second requires Docker at
/var/run/docker.sock, builds a fixture image, and removes its own resources.
Its gateway, app-server and provider responses are fixtures: it does not prove
Agent admission, a model call, or Compose orchestration.
Verify host routing relay diagnostics
On Linux, host-run Gateway clients reuse kubectl's allocated loopback port. The fixture maps that port to the Envoy Service's existing HTTPS target for in-cluster clients. Separate test processes and clusters can keep these routes open together without competing for host port 443. The scoped DNS override does not support independent concurrent teardown within one process.
On macOS, the host routing relay runs in a container. If it is not observed running, failed commands contribute their exit status; container state and redacted logs are reported when available. The fixture verifies its invocation label before reading or removing a container. Cleanup waits for the bounded launch before checking ownership. An interrupted launch reports an indeterminate outcome even if no container is visible; a delegated engine may still be creating it. Removal failures are reported unless the engine confirms absence. Each diagnostic command has a five-second timeout. Output tails keep up to eight lines, each with up to 256 characters of content plus a truncation marker. Interrupted or over-limit captures are omitted. A running-container check alone does not prove that the loopback listener bound.
To check relay startup diagnostics with an existing local runtime image, run
OCC_TEST_RUNTIME_IMAGE=<local-image> node --test tests/helpers/workspace-gateway-relay-container.test.ts.
These cases disable container networking and check real process exits, launch
errors, log redaction, and cleanup. They do not exercise Kubernetes or Gateway
routing and do not pull images.
Verify Codex startup probe recovery
With a running Docker engine and an existing immutable Node 24+ Linux image:
OCC_TEST_CODEX_PROBE_IMAGE=sha256:<local-image-id> \ node --test tests/integration/codex-model-probe.test.mjsThe image may be a repository digest; the test does not pull it. It uses a fixture CLI and removes its containers and temporary files. It takes about 95 seconds and does not prove provider compatibility.
Docker Compose development test environment
tests/integration/docker-compute-real.test.mjs starts the Compose stack and
checks the bootstrap service key, API authentication denials, Namespace networks
and empty-Namespace deletion. It also checks that OCC refuses a Harness
authentication binding and an Agent deployment without one (409). Model turns
return when Docker Compute supports Harness authentication, a Compute Driver
contract change. The workspace setup cases call the Driver directly.
pnpm podman:test selects Podman; unselected cases skip. The inputs are
OCC_TEST_DOCKER_COMPUTE_REAL or OCC_TEST_PODMAN_COMPUTE_REAL,
OCC_DOCKER_GATEWAY_IMAGE, OCC_DOCKER_AGENT_IMAGE (or shared
OCC_DOCKER_RUNTIME_IMAGE), OCC_TEST_OPENAI_MODEL and OPENAI_API_KEY, which
only the workspace setup cases pass to the runtime. See the test source for defaults.
See the Docker Compute support boundary.
Container publication registry proof
With Docker and Skopeo 1.13.3, run:
OCC_TEST_CONTAINER_REGISTRY=1 node --test tests/integration/container-registry-real.test.tsThe test pulls a digest-pinned registry image and removes its disposable loopback registry. It checks publication against that registry, not GHCR access or GitHub permissions. It skips without the selector.
Images and Helm
Image and Helm checks require Node 24+, installed dependencies, and Docker unless stated otherwise. Use locally built images or pull the immutable published images selected below. These checks make no model calls.
Check published images
On a native host for each target architecture, use the source commit that
produced the images. Follow image selection and registry authentication.
Set the immutable CONTROLLER_IMAGE and RUNTIME_IMAGE references, then run:
docker pull "$CONTROLLER_IMAGE"docker pull "$RUNTIME_IMAGE"OCC_TEST_PRODUCTION_IMAGE="$CONTROLLER_IMAGE" OCC_TEST_RUNTIME_IMAGE="$RUNTIME_IMAGE" \ node --test --test-concurrency=1 tests/integration/production-image-startup.test.mjs \ tests/integration/runtime-image-startup.test.ts \ tests/integration/runtime-image-gateway-workspace.test.ts \ tests/integration/runtime-image-public-github-read.test.mjs \ tests/integration/runtime-image-startup-probe.test.mjs \ tests/integration/runtime-image-codex-readiness.test.ts \ tests/integration/runtime-image-startup-termination.test.ts \ tests/integration/runtime-image-gateway-unclean-restart.test.ts \ tests/integration/runtime-image-gateway-retained-state.test.ts \ tests/integration/runtime-image-gateway-peer.test.ts \ tests/integration/runtime-image-native-worker.test.ts \ tests/integration/runtime-image-state-migration.test.ts \ tests/integration/runtime-image-managed-files.test.ts \ tests/integration/runtime-image-native-listener.test.ts \ tests/integration/repository-runtime-volume.test.tsAll selected cases must pass without skips for the exact pair before installation. Repeat for changed digests. An unset image selector skips its cases. The public GitHub read case uses stock Codex to read a pull request title from a local fixture.
The native release workflow runs a larger suite and prepares the Envoy image and reviewed Codex seccomp profile. For a prepared Image Runtime Startup lane, run the tests with the original state file before cleanup. The runner supplies the profile, and the tests check its path and SHA-256 against the preparation record. Cleanup removes the file with the run-owned cluster directory.
For a standalone run of the default Codex version where Docker's default profile blocks
the sandbox, obtain the reviewed manual file separately from the image export and set
OCC_TEST_CODEX_SECCOMP_PROFILE to its path. The smoke helper
checks the versioned filename and the file's SHA-256 against its manual pin.
Use the prepared lane when the manual file is unavailable or when testing a supported
historical Codex version.
The controller check expects an unreachable database; it does not prove connectivity. Runtime checks do not prove a model turn or Slack delivery.
Build images from the checkout
Build the runtime image and the controller
image using the production prerequisites.
Set CONTROLLER_IMAGE and RUNTIME_IMAGE to the local tags and run the image
suite above, omitting the docker pull commands.
Render the Helm chart
With Helm and yq supporting eval-all -o=json:
node --test tests/integration/production-kubernetes-packaging.test.mjs \ tests/integration/production-kubernetes-network-policy.test.tsMissing Helm or yq skips cases. Rendering does not install the chart or prove
live admission or NetworkPolicy enforcement. OCC_HELM_BIN can select Helm.
Development Compose packaging
With a Compose provider on PATH, run:
node --test tests/integration/development-packaging.test.mjs tests/integration/logging-packaging.test.tsThe tests inspect configuration without starting containers. Missing Compose or
required yq fails the cases; the logging Helm checks also require Helm.
Repository image-pair qualification
For fixture coverage, run node --test tests/integration/production-image-qualification.test.ts.
For real image-pair compatibility, use Linux as UID 1000 and stage immutable
images for the native Docker architecture. Set OCC_PROBE_CONTROLLER_IMAGE,
OCC_PROBE_BROKER_IMAGE, OCC_PROBE_OLD_CONTROLLER_IMAGE and
OCC_PROBE_OLD_BROKER_IMAGE. Select an old controller without the admission
probe and an old broker without durable-admission capability. Then run:
umask 077pair_state_dir=$(mktemp -d)node scripts/ci/run-tests.ts run image-pair-qualification \ --state "$pair_state_dir/state.json" --results "$pair_state_dir/results.json"The lane requires all four images and fails on skipped cases. It exercises the admission protocol in Docker. The test starts the older broker independently with prepared-git inputs to determine which refusal the upgrade command must report. If it exits before its control socket opens, the test starts the same image with its historical projected inputs. It uses a disposable, unregistered App key and a container with no external network. It checks the exact HTTP 404 response, then adds only the prepared-git authority arguments and verifies that the broker exits before opening the socket. The upgrade command uses prepared-git inputs for every invocation.
If cancellation leaves an oce-old-pair-* directory under the test's temporary
directory, read its owner.json. The testOwner field records the host, PID and
process start time. On that host, confirm the process has exited or the PID has
a different start time. For a remaining oce-old-pair-<probeOwner> container,
verify its org.openclaw.test.owner and openclaw.upgrade-probe labels match
testOwner and probeOwner, and its bind mounts point into that directory.
Remove the container by ID and remove that directory. Leave the fixture in place
if ownership is uncertain.
Runtime image startup test environment
The Codex readiness case runs a real app-server with no model credentials or external network. It exercises the standalone healthcheck and the generated resident HTTP listener before login/model startup. Both preserve the ordinary client's identity, omit per-poll notifications at production INFO logging, and reject incomplete RPCs, including disconnects before the result. This is local HTTP/protocol component proof, not full Agent startup or cluster routing. The existing Codex startup-probe case additionally checks repeated HTTP readiness after the complete wrapper starts the packaged server; only its upstream model provider is substituted by the fixture.
The runtime suite above uses task-owned Docker containers. In CI it requires the
reviewed OCC_TEST_CODEX_SECCOMP_PROFILE. If running inside a container against
a host Docker daemon, mount the repository and fixture temporary directory at
the same absolute host paths and set TMPDIR to that shared directory.
OCC_DOCKER_BIN selects an alternate executable. For emulated startup, set
OCC_TEST_IMAGE_TIMEOUT_MULTIPLIER to an integer from 1 to 10. Some startup
waits are sized for 8 CPUs and grow on runners with fewer CPUs, because CI runs
image test files side by side.
Repository runtime volume test environment
The runtime suite includes repository-runtime-volume.test.ts, which requires
Docker volume-subpath support. It exercises the installed client and removes
its owned container and volume. It does not prove Kubernetes fsGroup or live
GitHub behavior.
Verify installation image selections
Before a registry-backed installation, check the exact selected digests on each
native architecture as above. In the installation shell, compare them to the
prepared YAML. Stop if either comparison fails. For separate runtime images,
set the checked GATEWAY_IMAGE and AGENT_IMAGE digests explicitly:
: "${CONTROLLER_IMAGE:?Set the checked controller digest}"export GATEWAY_IMAGE="${GATEWAY_IMAGE:-${RUNTIME_IMAGE:?Set the checked runtime digest}}"export AGENT_IMAGE="${AGENT_IMAGE:-${RUNTIME_IMAGE:?Set the checked runtime digest}}"yq e -e '.images.controller == strenv(CONTROLLER_IMAGE)' "$OCC_INPUT_DIRECTORY/values.yaml" && \ yq e -e '.drivers.compute.configuration.images.gateway == strenv(GATEWAY_IMAGE) and .drivers.compute.configuration.images.agent == strenv(AGENT_IMAGE)' "$OCC_INPUT_DIRECTORY/installation.yaml"Repeat the image checks and comparisons when a digest changes. The local Kubernetes import path uses generated YAML and skips this comparison.
