diff --git a/Dockerfile b/Dockerfile index 3ef9421b589..6b147441e5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -118,6 +118,12 @@ COPY --from=build --chown=node:node /app/extensions ./extensions COPY --from=build --chown=node:node /app/skills ./skills COPY --from=build --chown=node:node /app/docs ./docs +# Docker live-test runners invoke `pnpm` inside the runtime image. +# Activate the exact pinned package manager now so the container does not +# rely on a first-run network fetch or missing shims under the non-root user. +RUN corepack enable && \ + corepack prepare "$(node -p "require('./package.json').packageManager")" --activate + # Install additional system packages needed by your skills or extensions. # Example: docker build --build-arg OPENCLAW_DOCKER_APT_PACKAGES="python3 wget" . ARG OPENCLAW_DOCKER_APT_PACKAGES="" diff --git a/docs/help/testing.md b/docs/help/testing.md index ff1da245025..9e965b4c769 100644 --- a/docs/help/testing.md +++ b/docs/help/testing.md @@ -353,6 +353,10 @@ These run `pnpm test:live` inside the repo Docker image, mounting your local con - Gateway networking (two containers, WS auth + health): `pnpm test:docker:gateway-network` (script: `scripts/e2e/gateway-network-docker.sh`) - Plugins (custom extension load + registry smoke): `pnpm test:docker:plugins` (script: `scripts/e2e/plugins-docker.sh`) +The live-model Docker runners also bind-mount the current checkout read-only and +stage it into a temporary workdir inside the container. This keeps the runtime +image slim while still running Vitest against your exact local source/config. + Manual ACP plain-language thread smoke (not CI): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` diff --git a/scripts/test-live-gateway-models-docker.sh b/scripts/test-live-gateway-models-docker.sh index 3cc5ed2bf0b..92ddb905ed5 100755 --- a/scripts/test-live-gateway-models-docker.sh +++ b/scripts/test-live-gateway-models-docker.sh @@ -12,6 +12,27 @@ if [[ -f "$PROFILE_FILE" ]]; then PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) fi +read -r -d '' LIVE_TEST_CMD <<'EOF' || true +set -euo pipefail +[ -f "$HOME/.profile" ] && source "$HOME/.profile" || true +tmp_dir="$(mktemp -d)" +cleanup() { + rm -rf "$tmp_dir" +} +trap cleanup EXIT +tar -C /src \ + --exclude=.git \ + --exclude=node_modules \ + --exclude=dist \ + --exclude=ui/dist \ + --exclude=ui/node_modules \ + -cf - . | tar -C "$tmp_dir" -xf - +ln -s /app/node_modules "$tmp_dir/node_modules" +ln -s /app/dist "$tmp_dir/dist" +cd "$tmp_dir" +pnpm test:live +EOF + echo "==> Build image: $IMAGE_NAME" docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/Dockerfile" "$ROOT_DIR" @@ -26,8 +47,9 @@ docker run --rm -t \ -e OPENCLAW_LIVE_GATEWAY_PROVIDERS="${OPENCLAW_LIVE_GATEWAY_PROVIDERS:-${CLAWDBOT_LIVE_GATEWAY_PROVIDERS:-}}" \ -e OPENCLAW_LIVE_GATEWAY_MAX_MODELS="${OPENCLAW_LIVE_GATEWAY_MAX_MODELS:-${CLAWDBOT_LIVE_GATEWAY_MAX_MODELS:-24}}" \ -e OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS="${OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS:-${CLAWDBOT_LIVE_GATEWAY_MODEL_TIMEOUT_MS:-}}" \ + -v "$ROOT_DIR":/src:ro \ -v "$CONFIG_DIR":/home/node/.openclaw \ -v "$WORKSPACE_DIR":/home/node/.openclaw/workspace \ "${PROFILE_MOUNT[@]}" \ "$IMAGE_NAME" \ - -lc "set -euo pipefail; [ -f \"$HOME/.profile\" ] && source \"$HOME/.profile\" || true; cd /app && pnpm test:live" + -lc "$LIVE_TEST_CMD" diff --git a/scripts/test-live-models-docker.sh b/scripts/test-live-models-docker.sh index f3aecc0049a..5e3e1d0a311 100755 --- a/scripts/test-live-models-docker.sh +++ b/scripts/test-live-models-docker.sh @@ -12,6 +12,27 @@ if [[ -f "$PROFILE_FILE" ]]; then PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) fi +read -r -d '' LIVE_TEST_CMD <<'EOF' || true +set -euo pipefail +[ -f "$HOME/.profile" ] && source "$HOME/.profile" || true +tmp_dir="$(mktemp -d)" +cleanup() { + rm -rf "$tmp_dir" +} +trap cleanup EXIT +tar -C /src \ + --exclude=.git \ + --exclude=node_modules \ + --exclude=dist \ + --exclude=ui/dist \ + --exclude=ui/node_modules \ + -cf - . | tar -C "$tmp_dir" -xf - +ln -s /app/node_modules "$tmp_dir/node_modules" +ln -s /app/dist "$tmp_dir/dist" +cd "$tmp_dir" +pnpm test:live +EOF + echo "==> Build image: $IMAGE_NAME" docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/Dockerfile" "$ROOT_DIR" @@ -27,8 +48,9 @@ docker run --rm -t \ -e OPENCLAW_LIVE_MAX_MODELS="${OPENCLAW_LIVE_MAX_MODELS:-${CLAWDBOT_LIVE_MAX_MODELS:-48}}" \ -e OPENCLAW_LIVE_MODEL_TIMEOUT_MS="${OPENCLAW_LIVE_MODEL_TIMEOUT_MS:-${CLAWDBOT_LIVE_MODEL_TIMEOUT_MS:-}}" \ -e OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS="${OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS:-${CLAWDBOT_LIVE_REQUIRE_PROFILE_KEYS:-}}" \ + -v "$ROOT_DIR":/src:ro \ -v "$CONFIG_DIR":/home/node/.openclaw \ -v "$WORKSPACE_DIR":/home/node/.openclaw/workspace \ "${PROFILE_MOUNT[@]}" \ "$IMAGE_NAME" \ - -lc "set -euo pipefail; [ -f \"$HOME/.profile\" ] && source \"$HOME/.profile\" || true; cd /app && pnpm test:live" + -lc "$LIVE_TEST_CMD"