From 4dd7bc6d8897fbfc77fe5105c277026af0ba2746 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Thu, 4 Jun 2026 19:09:23 -0700 Subject: [PATCH] fix(test): stage live docker home credentials --- scripts/lib/docker-e2e-scenarios.mjs | 8 ++- scripts/lib/live-docker-auth.sh | 52 ++++++++++++++++++- scripts/test-docker-all.mjs | 6 ++- scripts/test-live-acp-bind-docker.sh | 23 ++++++-- scripts/test-live-cli-backend-docker.sh | 21 ++++++-- scripts/test-live-codex-harness-docker.sh | 29 ++++++++--- scripts/test-live-gateway-models-docker.sh | 18 +++++-- scripts/test-live-models-docker.sh | 18 +++++-- scripts/test-live-subagent-announce-docker.sh | 18 +++++-- test/scripts/docker-e2e-plan.test.ts | 4 +- .../package-acceptance-workflow.test.ts | 21 +++++++- .../test-live-codex-harness-docker.test.ts | 7 ++- 12 files changed, 191 insertions(+), 34 deletions(-) diff --git a/scripts/lib/docker-e2e-scenarios.mjs b/scripts/lib/docker-e2e-scenarios.mjs index 3084b1a0e106..2d87c3a143a9 100644 --- a/scripts/lib/docker-e2e-scenarios.mjs +++ b/scripts/lib/docker-e2e-scenarios.mjs @@ -1,8 +1,14 @@ // Docker E2E scenario catalog. // Keep lane names, commands, image kind, timeout, resources, and release chunks // here. Planning and execution live in separate modules. +import { fileURLToPath } from "node:url"; export const DEFAULT_LIVE_RETRIES = 1; +const LIVE_DOCKER_DEFAULT_HARNESS_DIR = + /[\\/]\\.release-harness[\\/]/u.test(fileURLToPath(import.meta.url)) && + process.env.OPENCLAW_DOCKER_E2E_REPO_ROOT + ? ".release-harness" + : "."; const LIVE_ACP_TIMEOUT_MS = 20 * 60 * 1000; const LIVE_CLI_TIMEOUT_MS = 20 * 60 * 1000; const LIVE_PROFILE_TIMEOUT_MS = 30 * 60 * 1000; @@ -29,7 +35,7 @@ const LIVE_RETRY_PATTERNS = [ function liveDockerScriptCommand(script, envPrefix = "", options = {}) { const prefix = envPrefix ? `${envPrefix} ` : ""; const skipBuild = options.skipBuild === false ? "" : "OPENCLAW_SKIP_DOCKER_BUILD=1 "; - return `${prefix}${skipBuild}bash -c 'harness="\${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-}"; if [ -z "$harness" ]; then if [ -d .release-harness/scripts ]; then harness=.release-harness; else harness=.; fi; fi; OPENCLAW_LIVE_DOCKER_REPO_ROOT="\${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/${script}"'`; + return `${prefix}${skipBuild}bash -c 'harness="\${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-${LIVE_DOCKER_DEFAULT_HARNESS_DIR}}"; OPENCLAW_LIVE_DOCKER_REPO_ROOT="\${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/${script}"'`; } function lane(name, command, options = {}) { diff --git a/scripts/lib/live-docker-auth.sh b/scripts/lib/live-docker-auth.sh index baed506bf4bc..996df7e4baaa 100644 --- a/scripts/lib/live-docker-auth.sh +++ b/scripts/lib/live-docker-auth.sh @@ -30,7 +30,15 @@ openclaw_live_truthy() { } openclaw_live_is_ci() { - openclaw_live_truthy "${CI:-}" || openclaw_live_truthy "${GITHUB_ACTIONS:-}" + openclaw_live_truthy "${CI:-}" \ + || openclaw_live_truthy "${GITHUB_ACTIONS:-}" \ + || openclaw_live_truthy "${OPENCLAW_TESTBOX:-}" +} + +openclaw_live_uses_managed_bind_dirs() { + openclaw_live_is_ci \ + || [[ -n "${OPENCLAW_DOCKER_CACHE_HOME_DIR:-}" ]] \ + || [[ -n "${OPENCLAW_DOCKER_CLI_TOOLS_DIR:-}" ]] } openclaw_live_default_profile_file() { @@ -305,3 +313,45 @@ openclaw_live_stage_auth_into_home() { shift done } + +openclaw_live_prepare_bind_dir_for_container_user() { + local dir="${1:?directory required}" + + mkdir -p "$dir" + chmod u+rwx "$dir" || true +} + +openclaw_live_stage_profile_into_home() { + local dest_home="${1:?destination home directory required}" + local profile_file="${2:?profile file required}" + + [[ -f "$profile_file" && -r "$profile_file" ]] || return 1 + mkdir -p "$dest_home" + cp "$profile_file" "$dest_home/.profile" + chmod u+rw "$dest_home/.profile" || true +} + +openclaw_live_chown_bind_dirs_for_container_user() { + local image_name="${1:?image name required}" + local container_user="${2:?container user required}" + shift 2 + + local mount_args=() + local index=0 + local dir + for dir in "$@"; do + [[ -n "$dir" ]] || continue + mkdir -p "$dir" + mount_args+=(-v "$dir:/openclaw-bind-dir-$index") + index=$((index + 1)) + done + ((index > 0)) || return 0 + + docker run --rm \ + -u 0:0 \ + --entrypoint sh \ + -e OPENCLAW_BIND_DIR_USER="$container_user" \ + "${mount_args[@]}" \ + "$image_name" \ + -c 'for dir in /openclaw-bind-dir-*; do chown -R "$OPENCLAW_BIND_DIR_USER" "$dir"; done' +} diff --git a/scripts/test-docker-all.mjs b/scripts/test-docker-all.mjs index 8e4053dba2bb..c582a921b294 100644 --- a/scripts/test-docker-all.mjs +++ b/scripts/test-docker-all.mjs @@ -31,6 +31,10 @@ import { const SCRIPT_ROOT_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const ROOT_DIR = path.resolve(process.env.OPENCLAW_DOCKER_E2E_REPO_ROOT || SCRIPT_ROOT_DIR); +const LIVE_DOCKER_DEFAULT_HARNESS_DIR = + path.basename(SCRIPT_ROOT_DIR) === ".release-harness" && ROOT_DIR !== SCRIPT_ROOT_DIR + ? ".release-harness" + : "."; const DEFAULT_FAILURE_TAIL_LINES = 80; const DEFAULT_LANE_TIMEOUT_MS = 120 * 60 * 1000; const DEFAULT_LANE_START_STAGGER_MS = 2_000; @@ -361,7 +365,7 @@ function withResolvedPnpmCommand(command, env) { } function liveDockerHarnessScriptCommand(script) { - return `bash -c 'harness="\${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-}"; if [ -z "$harness" ]; then if [ -d .release-harness/scripts ]; then harness=.release-harness; else harness=.; fi; fi; OPENCLAW_LIVE_DOCKER_REPO_ROOT="\${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/${script}"'`; + return `bash -c 'harness="\${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-${LIVE_DOCKER_DEFAULT_HARNESS_DIR}}"; OPENCLAW_LIVE_DOCKER_REPO_ROOT="\${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/${script}"'`; } async function loadTimingStore(file, enabled) { diff --git a/scripts/test-live-acp-bind-docker.sh b/scripts/test-live-acp-bind-docker.sh index dcbe9c3a9672..bfbdf23bba96 100644 --- a/scripts/test-live-acp-bind-docker.sh +++ b/scripts/test-live-acp-bind-docker.sh @@ -85,16 +85,15 @@ else CACHE_HOME_DIR="$HOME/.cache/openclaw/docker-cache" fi -mkdir -p "$CLI_TOOLS_DIR" -mkdir -p "$CACHE_HOME_DIR" -if openclaw_live_is_ci; then +openclaw_live_prepare_bind_dir_for_container_user "$CLI_TOOLS_DIR" +openclaw_live_prepare_bind_dir_for_container_user "$CACHE_HOME_DIR" +if openclaw_live_uses_managed_bind_dirs; then DOCKER_USER="$(id -u):$(id -g)" fi PROFILE_MOUNT=() PROFILE_STATUS="none" if [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then - PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) PROFILE_STATUS="$PROFILE_FILE" fi @@ -326,10 +325,16 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do DOCKER_HOME_MOUNT=() DOCKER_AUTH_PRESTAGED=0 - if openclaw_live_is_ci; then + if openclaw_live_uses_managed_bind_dirs; then DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")" TEMP_DIRS+=("$DOCKER_HOME_DIR") + openclaw_live_prepare_bind_dir_for_container_user "$DOCKER_HOME_DIR" DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node) + if [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then + openclaw_live_stage_profile_into_home "$DOCKER_HOME_DIR" "$PROFILE_FILE" + fi + elif [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then + PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) fi if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then @@ -376,6 +381,14 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do echo "==> Profile file: $PROFILE_STATUS" echo "==> Auth dirs: ${AUTH_DIRS_CSV:-none}" echo "==> Auth files: ${AUTH_FILES_CSV:-none}" + if openclaw_live_uses_managed_bind_dirs; then + openclaw_live_chown_bind_dirs_for_container_user \ + "$LIVE_IMAGE_NAME" \ + "$DOCKER_USER" \ + "$CLI_TOOLS_DIR" \ + "$CACHE_HOME_DIR" \ + "${DOCKER_HOME_DIR:-}" + fi DOCKER_RUN_ARGS=() openclaw_live_init_docker_run_args DOCKER_RUN_ARGS "${OPENCLAW_LIVE_ACP_BIND_DOCKER_RUN_TIMEOUT:-2700s}" DOCKER_RUN_ARGS+=(--rm -t \ diff --git a/scripts/test-live-cli-backend-docker.sh b/scripts/test-live-cli-backend-docker.sh index b961ebbe9f3a..84b7ea5e0dd9 100644 --- a/scripts/test-live-cli-backend-docker.sh +++ b/scripts/test-live-cli-backend-docker.sh @@ -108,12 +108,13 @@ else CACHE_HOME_DIR="$HOME/.cache/openclaw/docker-cache" fi -mkdir -p "$CLI_TOOLS_DIR" -mkdir -p "$CACHE_HOME_DIR" -if openclaw_live_is_ci; then +openclaw_live_prepare_bind_dir_for_container_user "$CLI_TOOLS_DIR" +openclaw_live_prepare_bind_dir_for_container_user "$CACHE_HOME_DIR" +if openclaw_live_uses_managed_bind_dirs; then DOCKER_USER="$(id -u):$(id -g)" DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")" TEMP_DIRS+=("$DOCKER_HOME_DIR") + openclaw_live_prepare_bind_dir_for_container_user "$DOCKER_HOME_DIR" DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node) fi @@ -170,7 +171,11 @@ fi PROFILE_MOUNT=() PROFILE_STATUS="none" if [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then - PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then + openclaw_live_stage_profile_into_home "$DOCKER_HOME_DIR" "$PROFILE_FILE" + else + PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + fi PROFILE_STATUS="$PROFILE_FILE" fi @@ -397,6 +402,14 @@ node scripts/test-live.mjs -- src/gateway/gateway-cli-backend.live.test.ts EOF OPENCLAW_LIVE_DOCKER_REPO_ROOT="$ROOT_DIR" "$TRUSTED_HARNESS_DIR/scripts/test-live-build-docker.sh" +if openclaw_live_uses_managed_bind_dirs; then + openclaw_live_chown_bind_dirs_for_container_user \ + "$LIVE_IMAGE_NAME" \ + "$DOCKER_USER" \ + "$CLI_TOOLS_DIR" \ + "$CACHE_HOME_DIR" \ + "${DOCKER_HOME_DIR:-}" +fi echo "==> Run CLI backend live test in Docker" echo "==> Model: $CLI_MODEL" diff --git a/scripts/test-live-codex-harness-docker.sh b/scripts/test-live-codex-harness-docker.sh index d5d67fc48ed6..9a187d676189 100644 --- a/scripts/test-live-codex-harness-docker.sh +++ b/scripts/test-live-codex-harness-docker.sh @@ -29,7 +29,7 @@ DOCKER_EXTRA_ENV_FILES=() DOCKER_AUTH_PRESTAGED=0 openclaw_live_codex_harness_is_ci() { - [[ -n "${CI:-}" && "${CI:-}" != "false" ]] || [[ -n "${GITHUB_ACTIONS:-}" && "${GITHUB_ACTIONS:-}" != "false" ]] + openclaw_live_is_ci } openclaw_live_codex_harness_append_build_extension() { @@ -106,21 +106,20 @@ else CACHE_HOME_DIR="$HOME/.cache/openclaw/docker-cache" fi -mkdir -p "$CLI_TOOLS_DIR" -mkdir -p "$CACHE_HOME_DIR" -if openclaw_live_codex_harness_is_ci; then - chmod 0777 "$CLI_TOOLS_DIR" "$CACHE_HOME_DIR" || true -fi -if openclaw_live_codex_harness_is_ci; then +openclaw_live_prepare_bind_dir_for_container_user "$CLI_TOOLS_DIR" +openclaw_live_prepare_bind_dir_for_container_user "$CACHE_HOME_DIR" +if openclaw_live_uses_managed_bind_dirs; then DOCKER_USER="$(id -u):$(id -g)" DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")" TEMP_DIRS+=("$DOCKER_HOME_DIR") + openclaw_live_prepare_bind_dir_for_container_user "$DOCKER_HOME_DIR" DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node) fi if [[ "$CODEX_HARNESS_AUTH_MODE" == "api-key" ]]; then if [[ -z "${DOCKER_HOME_DIR:-}" ]]; then DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")" TEMP_DIRS+=("$DOCKER_HOME_DIR") + openclaw_live_prepare_bind_dir_for_container_user "$DOCKER_HOME_DIR" DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node) fi CONFIG_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-config.XXXXXX")" @@ -134,7 +133,11 @@ fi PROFILE_MOUNT=() PROFILE_STATUS="none" if [[ "$CODEX_HARNESS_AUTH_MODE" != "api-key" && -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then - PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then + openclaw_live_stage_profile_into_home "$DOCKER_HOME_DIR" "$PROFILE_FILE" + else + PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + fi PROFILE_STATUS="$PROFILE_FILE" elif [[ "$CODEX_HARNESS_AUTH_MODE" == "api-key" ]]; then PROFILE_STATUS="api-key-env" @@ -310,6 +313,16 @@ openclaw_live_codex_harness_append_build_extension codex OPENCLAW_SKIP_DOCKER_BUILD=0 export OPENCLAW_SKIP_DOCKER_BUILD OPENCLAW_LIVE_DOCKER_REPO_ROOT="$ROOT_DIR" "$TRUSTED_HARNESS_DIR/scripts/test-live-build-docker.sh" +if openclaw_live_uses_managed_bind_dirs; then + openclaw_live_chown_bind_dirs_for_container_user \ + "$LIVE_IMAGE_NAME" \ + "$DOCKER_USER" \ + "$CLI_TOOLS_DIR" \ + "$CACHE_HOME_DIR" \ + "$CONFIG_DIR" \ + "$WORKSPACE_DIR" \ + "${DOCKER_HOME_DIR:-}" +fi echo "==> Run Codex harness live test in Docker" echo "==> Model: ${OPENCLAW_LIVE_CODEX_HARNESS_MODEL:-codex/gpt-5.5}" diff --git a/scripts/test-live-gateway-models-docker.sh b/scripts/test-live-gateway-models-docker.sh index 742f19d26a2c..73e85a19f337 100755 --- a/scripts/test-live-gateway-models-docker.sh +++ b/scripts/test-live-gateway-models-docker.sh @@ -36,18 +36,23 @@ elif openclaw_live_is_ci; then else CACHE_HOME_DIR="$HOME/.cache/openclaw/docker-cache" fi -mkdir -p "$CACHE_HOME_DIR" -if openclaw_live_is_ci; then +openclaw_live_prepare_bind_dir_for_container_user "$CACHE_HOME_DIR" +if openclaw_live_uses_managed_bind_dirs; then DOCKER_USER="$(id -u):$(id -g)" DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")" TEMP_DIRS+=("$DOCKER_HOME_DIR") + openclaw_live_prepare_bind_dir_for_container_user "$DOCKER_HOME_DIR" DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node) fi PROFILE_MOUNT=() PROFILE_STATUS="none" if [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then - PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then + openclaw_live_stage_profile_into_home "$DOCKER_HOME_DIR" "$PROFILE_FILE" + else + PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + fi PROFILE_STATUS="$PROFILE_FILE" fi @@ -162,6 +167,13 @@ node scripts/test-live.mjs -- src/gateway/gateway-models.profiles.live.test.ts EOF OPENCLAW_LIVE_DOCKER_REPO_ROOT="$ROOT_DIR" "$TRUSTED_HARNESS_DIR/scripts/test-live-build-docker.sh" +if openclaw_live_uses_managed_bind_dirs; then + openclaw_live_chown_bind_dirs_for_container_user \ + "$LIVE_IMAGE_NAME" \ + "$DOCKER_USER" \ + "$CACHE_HOME_DIR" \ + "${DOCKER_HOME_DIR:-}" +fi echo "==> Run gateway live model tests (profile keys)" echo "==> Target: src/gateway/gateway-models.profiles.live.test.ts" diff --git a/scripts/test-live-models-docker.sh b/scripts/test-live-models-docker.sh index 634086dcd450..53641494b605 100755 --- a/scripts/test-live-models-docker.sh +++ b/scripts/test-live-models-docker.sh @@ -56,18 +56,23 @@ elif openclaw_live_is_ci; then else CACHE_HOME_DIR="$HOME/.cache/openclaw/docker-cache" fi -mkdir -p "$CACHE_HOME_DIR" -if openclaw_live_is_ci; then +openclaw_live_prepare_bind_dir_for_container_user "$CACHE_HOME_DIR" +if openclaw_live_uses_managed_bind_dirs; then DOCKER_USER="$(id -u):$(id -g)" DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")" TEMP_DIRS+=("$DOCKER_HOME_DIR") + openclaw_live_prepare_bind_dir_for_container_user "$DOCKER_HOME_DIR" DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node) fi PROFILE_MOUNT=() PROFILE_STATUS="none" if [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then - PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then + openclaw_live_stage_profile_into_home "$DOCKER_HOME_DIR" "$PROFILE_FILE" + else + PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + fi PROFILE_STATUS="$PROFILE_FILE" fi @@ -191,6 +196,13 @@ node scripts/test-live.mjs -- src/agents/models.profiles.live.test.ts EOF OPENCLAW_LIVE_DOCKER_REPO_ROOT="$ROOT_DIR" "$TRUSTED_HARNESS_DIR/scripts/test-live-build-docker.sh" +if openclaw_live_uses_managed_bind_dirs; then + openclaw_live_chown_bind_dirs_for_container_user \ + "$LIVE_IMAGE_NAME" \ + "$DOCKER_USER" \ + "$CACHE_HOME_DIR" \ + "${DOCKER_HOME_DIR:-}" +fi echo "==> Run live model tests (profile keys)" echo "==> Target: src/agents/models.profiles.live.test.ts" diff --git a/scripts/test-live-subagent-announce-docker.sh b/scripts/test-live-subagent-announce-docker.sh index 7f78bad3822c..fcc62278831a 100644 --- a/scripts/test-live-subagent-announce-docker.sh +++ b/scripts/test-live-subagent-announce-docker.sh @@ -39,19 +39,24 @@ elif openclaw_live_is_ci; then else CACHE_HOME_DIR="$HOME/.cache/openclaw/docker-cache" fi -mkdir -p "$CACHE_HOME_DIR" +openclaw_live_prepare_bind_dir_for_container_user "$CACHE_HOME_DIR" -if openclaw_live_is_ci; then +if openclaw_live_uses_managed_bind_dirs; then DOCKER_USER="$(id -u):$(id -g)" DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")" TEMP_DIRS+=("$DOCKER_HOME_DIR") + openclaw_live_prepare_bind_dir_for_container_user "$DOCKER_HOME_DIR" DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node) fi PROFILE_MOUNT=() PROFILE_STATUS="none" if [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then - PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then + openclaw_live_stage_profile_into_home "$DOCKER_HOME_DIR" "$PROFILE_FILE" + else + PROFILE_MOUNT=(-v "$PROFILE_FILE":/home/node/.profile:ro) + fi PROFILE_STATUS="$PROFILE_FILE" fi @@ -119,6 +124,13 @@ node scripts/test-live.mjs -- src/agents/subagent-announce.live.test.ts -- --rep EOF OPENCLAW_LIVE_DOCKER_REPO_ROOT="$ROOT_DIR" "$TRUSTED_HARNESS_DIR/scripts/test-live-build-docker.sh" +if openclaw_live_uses_managed_bind_dirs; then + openclaw_live_chown_bind_dirs_for_container_user \ + "$LIVE_IMAGE_NAME" \ + "$DOCKER_USER" \ + "$CACHE_HOME_DIR" \ + "${DOCKER_HOME_DIR:-}" +fi echo "==> Run subagent announce live test in Docker" echo "==> Target: src/agents/subagent-announce.live.test.ts" diff --git a/test/scripts/docker-e2e-plan.test.ts b/test/scripts/docker-e2e-plan.test.ts index 59235df95073..9912c55c6fa4 100644 --- a/test/scripts/docker-e2e-plan.test.ts +++ b/test/scripts/docker-e2e-plan.test.ts @@ -731,7 +731,7 @@ describe("scripts/lib/docker-e2e-plan", () => { expect(plan.lanes.map(summarizeLane)).toEqual([ { command: - 'OPENCLAW_SKIP_DOCKER_BUILD=1 bash -c \'harness="${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-}"; if [ -z "$harness" ]; then if [ -d .release-harness/scripts ]; then harness=.release-harness; else harness=.; fi; fi; OPENCLAW_LIVE_DOCKER_REPO_ROOT="${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/e2e/codex-npm-plugin-live-docker.sh"\'', + 'OPENCLAW_SKIP_DOCKER_BUILD=1 bash -c \'harness="${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-.}"; OPENCLAW_LIVE_DOCKER_REPO_ROOT="${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/e2e/codex-npm-plugin-live-docker.sh"\'', imageKind: "bare", live: true, name: "live-codex-npm-plugin", @@ -826,7 +826,7 @@ describe("scripts/lib/docker-e2e-plan", () => { expect(plan.lanes).toHaveLength(1); const lane = requireFirstLane(plan); expect(lane.command).toBe( - 'OPENCLAW_LIVE_ACP_BIND_AGENT=droid OPENCLAW_LIVE_ACP_BIND_REQUIRE_TRANSCRIPT=1 OPENCLAW_SKIP_DOCKER_BUILD=1 bash -c \'harness="${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-}"; if [ -z "$harness" ]; then if [ -d .release-harness/scripts ]; then harness=.release-harness; else harness=.; fi; fi; OPENCLAW_LIVE_DOCKER_REPO_ROOT="${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/test-live-acp-bind-docker.sh"\'', + 'OPENCLAW_LIVE_ACP_BIND_AGENT=droid OPENCLAW_LIVE_ACP_BIND_REQUIRE_TRANSCRIPT=1 OPENCLAW_SKIP_DOCKER_BUILD=1 bash -c \'harness="${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-.}"; OPENCLAW_LIVE_DOCKER_REPO_ROOT="${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/test-live-acp-bind-docker.sh"\'', ); expect(lane.imageKind).toBeUndefined(); expect(lane.live).toBe(true); diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 203a5f4dff2c..afd6bbeb1762 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -790,9 +790,14 @@ describe("package artifact reuse", () => { 'command: OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 20m bash .release-harness/scripts/test-live-subagent-announce-docker.sh', ); expect(scenarios).toContain("function liveDockerScriptCommand"); + expect(scenarios).toContain("const LIVE_DOCKER_DEFAULT_HARNESS_DIR"); + expect(scenarios).toContain("fileURLToPath(import.meta.url)"); + expect(scenarios).toContain('? ".release-harness"'); + expect(scenarios).toContain("process.env.OPENCLAW_DOCKER_E2E_REPO_ROOT"); expect(scenarios).toContain( - "if [ -d .release-harness/scripts ]; then harness=.release-harness", + 'harness="\\${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-${LIVE_DOCKER_DEFAULT_HARNESS_DIR}}"', ); + expect(scenarios).not.toContain("harness=.release-harness"); expect(scenarios).toMatch(/liveDockerScriptCommand\(\s*"test-live-models-docker\.sh"/u); expect(scenarios).toMatch(/liveDockerScriptCommand\(\s*"test-live-gateway-models-docker\.sh"/u); expect(scenarios).toMatch(/liveDockerScriptCommand\(\s*"test-live-cli-backend-docker\.sh"/u); @@ -805,9 +810,21 @@ describe("package artifact reuse", () => { /liveDockerScriptCommand\(\s*"test-live-subagent-announce-docker\.sh"/u, ); expect(scheduler).toContain("function liveDockerHarnessScriptCommand"); + expect(scheduler).toContain("const LIVE_DOCKER_DEFAULT_HARNESS_DIR"); + expect(scheduler).toContain('path.basename(SCRIPT_ROOT_DIR) === ".release-harness"'); + expect(scheduler).toContain("ROOT_DIR !== SCRIPT_ROOT_DIR"); + expect(scheduler).toContain( + 'harness="\\${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-${LIVE_DOCKER_DEFAULT_HARNESS_DIR}}"', + ); + expect(scheduler).not.toContain("harness=.release-harness"); expect(scheduler).toContain('liveDockerHarnessScriptCommand("test-live-build-docker.sh")'); expect(liveDockerAuth).toContain("codex-cli | openai)"); expect(liveDockerAuth).toContain("openclaw_live_init_docker_run_args()"); + expect(liveDockerAuth).toContain("openclaw_live_stage_profile_into_home()"); + expect(liveDockerAuth).toContain("openclaw_live_chown_bind_dirs_for_container_user()"); + expect(liveDockerAuth).toContain("openclaw_live_uses_managed_bind_dirs()"); + expect(liveDockerAuth).toContain('openclaw_live_truthy "${OPENCLAW_TESTBOX:-}"'); + expect(liveDockerAuth).toContain('[[ -n "${OPENCLAW_DOCKER_CACHE_HOME_DIR:-}" ]]'); expect(liveDockerAuth).toContain( 'timeout_value="${2:-${OPENCLAW_LIVE_DOCKER_RUN_TIMEOUT:-2700s}}"', ); @@ -825,10 +842,12 @@ describe("package artifact reuse", () => { expect(script).toContain('source "$TRUSTED_HARNESS_DIR/scripts/lib/live-docker-auth.sh"'); expect(script).not.toContain('source "$ROOT_DIR/scripts/lib/live-docker-auth.sh"'); expect(script).toContain("openclaw_live_init_docker_run_args DOCKER_RUN_ARGS"); + expect(script).toContain("openclaw_live_prepare_bind_dir_for_container_user"); expect(script).toContain("DOCKER_RUN_ARGS+=(--rm -t \\"); expect(script).not.toContain("DOCKER_RUN_ARGS=(docker run --rm -t \\"); } for (const script of sharedLiveScripts) { + expect(script).toContain("openclaw_live_uses_managed_bind_dirs"); expect(script).toContain( 'OPENCLAW_LIVE_DOCKER_REPO_ROOT="$ROOT_DIR" "$TRUSTED_HARNESS_DIR/scripts/test-live-build-docker.sh"', ); diff --git a/test/scripts/test-live-codex-harness-docker.test.ts b/test/scripts/test-live-codex-harness-docker.test.ts index cbd230058894..dcdec2ed949c 100644 --- a/test/scripts/test-live-codex-harness-docker.test.ts +++ b/test/scripts/test-live-codex-harness-docker.test.ts @@ -15,10 +15,12 @@ describe("scripts/test-live-codex-harness-docker.sh", () => { expect(script).toContain('DOCKER_CACHE_CONTAINER_DIR="/tmp/openclaw-cache"'); expect(script).toContain('DOCKER_CLI_TOOLS_CONTAINER_DIR="/tmp/openclaw-npm-global"'); expect(script).toContain("openclaw_live_codex_harness_is_ci()"); - expect(script).toContain('[[ -n "${CI:-}" && "${CI:-}" != "false" ]]'); + expect(script).toContain("openclaw_live_is_ci"); expect(script).toContain('-e XDG_CACHE_HOME="$DOCKER_CACHE_CONTAINER_DIR"'); expect(script).toContain('-e NPM_CONFIG_PREFIX="$DOCKER_CLI_TOOLS_CONTAINER_DIR"'); - expect(script).toContain('chmod 0777 "$CLI_TOOLS_DIR" "$CACHE_HOME_DIR" || true'); + expect(script).toContain('openclaw_live_prepare_bind_dir_for_container_user "$CLI_TOOLS_DIR"'); + expect(script).toContain('openclaw_live_prepare_bind_dir_for_container_user "$CACHE_HOME_DIR"'); + expect(script).toContain("openclaw_live_uses_managed_bind_dirs"); expect(script).toContain('-v "$CACHE_HOME_DIR":"$DOCKER_CACHE_CONTAINER_DIR"'); expect(script).toContain('-v "$CLI_TOOLS_DIR":"$DOCKER_CLI_TOOLS_CONTAINER_DIR"'); expect(script).not.toContain('-v "$CACHE_HOME_DIR":/home/node/.cache'); @@ -51,6 +53,7 @@ describe("scripts/test-live-codex-harness-docker.sh", () => { const script = fs.readFileSync(SCRIPT_PATH, "utf8"); expect(script).toContain('DOCKER_USER="$(id -u):$(id -g)"'); + expect(script).toContain("if openclaw_live_uses_managed_bind_dirs; then"); expect(script).toContain('if [[ "$CODEX_HARNESS_AUTH_MODE" == "api-key" ]]; then'); expect(script).toContain('if [[ -z "${DOCKER_HOME_DIR:-}" ]]; then'); expect(script).not.toContain('DOCKER_USER="0:0"');