CI: stabilize live release lanes (#67838)

* CI: stabilize live release lanes

* CI: widen codex live exclusions

* Gateway: stop live config/auth lazy re-imports

* CI: mount writable live Docker homes

* Live: tighten retry and provider filter overrides

* CI: use API-key auth for codex live lanes

* CI: fix remaining live lanes

* CI: stop forwarding live OpenAI base URLs

* Gateway: fix live startup loader regression

* CI: stop expanding OpenAI keys in live Docker lanes

* CI: stop expanding installer secrets in Docker

* CI: tighten live secret boundaries

* Gateway: pin Codex harness base URL

* CI: fix reusable workflow runner label

* CI: avoid template expansion in live ref guard

* CI: tighten live trust gate

* Gateway: ignore empty Codex harness base URL

* CI: stabilize remaining live lanes

* CI: harden live retries and canvas auth test

* CI: extend cron live probe budget

* CI: keep codex harness lane on api-key auth

* CI: stage live Docker OpenAI auth via env files

* CI: bootstrap codex login for Docker API-key lanes

* CI: accept hosted-runner codex fallback responses

* CI: accept additional codex sandbox fallback text

* CI: accept hosted-runner live fallback variants

* CI: accept codex current-model fallback

* CI: broaden codex sandbox model fallbacks

* CI: cover extra codex sandbox wording

* CI: extend cli backend cron retry budget

* CI: match codex models fallbacks by predicate

* CI: accept configured-models live fallback

* CI: relax OpenAI websocket warmup timeout

* CI: accept extra codex model fallback wording

* CI: generalize codex model fallback matching

* CI: retry cron verify cancellation wording

* CI: accept interactive codex model entrypoint fallback

* Agents: stabilize Claude bundle skill command test

* CI: prestage live Docker auth homes

* Tests: accept current Codex models wording

* CI: stabilize remaining live lanes

* Tests: widen CLI backend live timeout

* Tests: accept current Codex model summary wording

* CI: disable codex-cli image probe in Docker lane

* Tests: respect CLI override for Codex Docker login

* Tests: accept current Codex session models header

* CI: stabilize remaining live validation lanes

* CI: preserve Gemini ACP coverage in auth fallback

* CI: fix final live validation blockers

* CI: restore Codex auth for CLI backend lane

* CI: drop local Codex config in live Docker lane

* Tests: tolerate Codex cron and model reply drift

* Tests: accept current Codex live replies

* Tests: retry more Codex cron retry wording

* Tests: accept environment-cancelled Codex cron retries

* Tests: retry blank Codex cron probe replies

* Tests: broaden Codex cron retry wording

* Tests: require explicit Codex cron retry replies

* Tests: accept current Codex models environment wording

* CI: restore trusted Codex config in live lane

* CI: bypass nested Codex sandbox in docker

* CI: instrument live codex cron lane

* CI: forward live CLI resume args

* Tests: accept interactive Codex model selection

* Tests: bound websocket warm-up live lane

* CI: close live lane review gaps

* Tests: lazy-load gateway live server

* Tests: avoid gateway live loader regression

* CI: scope reusable workflow secrets

* Tests: tighten codex models live assertion

* Tests: normalize OpenAI speech live text
This commit is contained in:
Onur
2026-04-18 03:18:12 +02:00
committed by GitHub
parent a22b789547
commit 361750775d
32 changed files with 1598 additions and 190 deletions

View File

@@ -18,12 +18,31 @@ openclaw_live_trim() {
printf '%s' "$value"
}
openclaw_live_validate_relative_home_path() {
local value
value="$(openclaw_live_trim "${1:-}")"
[[ -n "$value" ]] || {
echo "ERROR: empty auth path." >&2
return 1
}
case "$value" in
/* | *..* | *\\* | *:*)
echo "ERROR: invalid auth path '$value'." >&2
return 1
;;
esac
printf '%s' "$value"
}
openclaw_live_normalize_auth_dir() {
local value
value="$(openclaw_live_trim "${1:-}")"
[[ -n "$value" ]] || return 1
value="${value#.}"
printf '.%s' "$value"
if [[ "$value" != .* ]]; then
value=".$value"
fi
value="$(openclaw_live_validate_relative_home_path "$value")" || return 1
printf '%s' "$value"
}
openclaw_live_should_include_auth_dir_for_provider() {
@@ -143,3 +162,44 @@ openclaw_live_join_csv() {
fi
done
}
openclaw_live_stage_auth_into_home() {
local dest_home="${1:?destination home directory required}"
shift
local mode="dirs"
local relative_path source_path dest_path
mkdir -p "$dest_home"
chmod u+rwx "$dest_home" || true
while (($# > 0)); do
case "$1" in
--files)
mode="files"
shift
continue
;;
esac
relative_path="$(openclaw_live_validate_relative_home_path "$1")" || return 1
source_path="$HOME/$relative_path"
dest_path="$dest_home/$relative_path"
if [[ "$mode" == "dirs" ]]; then
if [[ -d "$source_path" ]]; then
mkdir -p "$dest_path"
cp -R "$source_path"/. "$dest_path"
chmod -R u+rwX "$dest_path" || true
fi
else
if [[ -f "$source_path" ]]; then
mkdir -p "$(dirname "$dest_path")"
cp "$source_path" "$dest_path"
chmod u+rw "$dest_path" || true
fi
fi
shift
done
}

View File

@@ -0,0 +1,51 @@
import fs from "node:fs/promises";
import path from "node:path";
function tomlString(value: string): string {
return JSON.stringify(value);
}
export function buildCiSafeCodexConfig(params: {
projectPath: string;
approvalPolicy?: string;
sandboxMode?: string;
}): string {
if (!params.projectPath || typeof params.projectPath !== "string") {
throw new Error("projectPath is required.");
}
const resolvedProjectPath = path.resolve(params.projectPath);
const approvalPolicy = params.approvalPolicy ?? "never";
const sandboxMode = params.sandboxMode ?? "workspace-write";
return [
"# Generated for Codex CI runs.",
"# Keep the checked-out repo trusted while avoiding maintainer-local",
"# provider/profile overrides that do not exist on CI runners.",
`approval_policy = ${tomlString(approvalPolicy)}`,
`sandbox_mode = ${tomlString(sandboxMode)}`,
"",
`[projects.${tomlString(resolvedProjectPath)}]`,
'trust_level = "trusted"',
"",
].join("\n");
}
export async function writeCiSafeCodexConfig(params: {
outputPath: string;
projectPath: string;
approvalPolicy?: string;
sandboxMode?: string;
}): Promise<string> {
if (!params.outputPath || typeof params.outputPath !== "string") {
throw new Error("outputPath is required.");
}
const rendered = buildCiSafeCodexConfig(params);
await fs.mkdir(path.dirname(params.outputPath), { recursive: true });
await fs.writeFile(params.outputPath, rendered, "utf-8");
return rendered;
}
if (path.basename(process.argv[1] ?? "") === "prepare-codex-ci-config.ts") {
const outputPath = process.argv[2];
const projectPath = process.argv[3] ?? process.cwd();
await writeCiSafeCodexConfig({ outputPath, projectPath });
}

View File

@@ -24,7 +24,7 @@ docker run --rm \
-e OPENCLAW_INSTALL_E2E_PREVIOUS="${OPENCLAW_INSTALL_E2E_PREVIOUS:-}" \
-e OPENCLAW_INSTALL_E2E_SKIP_PREVIOUS="${OPENCLAW_INSTALL_E2E_SKIP_PREVIOUS:-0}" \
-e OPENCLAW_NO_ONBOARD=1 \
-e OPENAI_API_KEY="$OPENAI_API_KEY" \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
-e ANTHROPIC_API_TOKEN="$ANTHROPIC_API_TOKEN" \
-e OPENAI_API_KEY \
-e ANTHROPIC_API_KEY \
-e ANTHROPIC_API_TOKEN \
"$IMAGE_NAME"

View File

@@ -11,6 +11,8 @@ PROFILE_FILE="${OPENCLAW_PROFILE_FILE:-$HOME/.profile}"
ACP_AGENT_LIST_RAW="${OPENCLAW_LIVE_ACP_BIND_AGENTS:-${OPENCLAW_LIVE_ACP_BIND_AGENT:-claude,codex,gemini}}"
TEMP_DIRS=()
DOCKER_USER="${OPENCLAW_DOCKER_USER:-node}"
DOCKER_HOME_MOUNT=()
DOCKER_AUTH_PRESTAGED=0
openclaw_live_acp_bind_resolve_auth_provider() {
case "${1:-}" in
@@ -80,27 +82,29 @@ export npm_config_cache="$NPM_CONFIG_CACHE"
mkdir -p "$NPM_CONFIG_PREFIX" "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE"
chmod 700 "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE" || true
export PATH="$NPM_CONFIG_PREFIX/bin:$PATH"
IFS=',' read -r -a auth_dirs <<<"${OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED:-}"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_dirs[@]} > 0)); then
for auth_dir in "${auth_dirs[@]}"; do
[ -n "$auth_dir" ] || continue
if [ -d "/host-auth/$auth_dir" ]; then
mkdir -p "$HOME/$auth_dir"
cp -R "/host-auth/$auth_dir/." "$HOME/$auth_dir"
chmod -R u+rwX "$HOME/$auth_dir" || true
fi
done
fi
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
if [ "${OPENCLAW_DOCKER_AUTH_PRESTAGED:-0}" != "1" ]; then
IFS=',' read -r -a auth_dirs <<<"${OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED:-}"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_dirs[@]} > 0)); then
for auth_dir in "${auth_dirs[@]}"; do
[ -n "$auth_dir" ] || continue
if [ -d "/host-auth/$auth_dir" ]; then
mkdir -p "$HOME/$auth_dir"
cp -R "/host-auth/$auth_dir/." "$HOME/$auth_dir"
chmod -R u+rwX "$HOME/$auth_dir" || true
fi
done
fi
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
fi
fi
agent="${OPENCLAW_LIVE_ACP_BIND_AGENT:-claude}"
case "$agent" in
@@ -217,9 +221,23 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do
AUTH_FILES_CSV="$(openclaw_live_join_csv "${AUTH_FILES[@]}")"
fi
DOCKER_HOME_MOUNT=()
DOCKER_AUTH_PRESTAGED=0
if [[ "${CI:-}" == "true" || "${GITHUB_ACTIONS:-}" == "true" ]]; then
DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")"
TEMP_DIRS+=("$DOCKER_HOME_DIR")
DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node)
fi
if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then
openclaw_live_stage_auth_into_home "$DOCKER_HOME_DIR" "${AUTH_DIRS[@]}" --files "${AUTH_FILES[@]}"
DOCKER_AUTH_PRESTAGED=1
fi
EXTERNAL_AUTH_MOUNTS=()
if ((${#AUTH_DIRS[@]} > 0)); then
for auth_dir in "${AUTH_DIRS[@]}"; do
auth_dir="$(openclaw_live_validate_relative_home_path "$auth_dir")"
host_path="$HOME/$auth_dir"
if [[ -d "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth/"$auth_dir":ro)
@@ -228,6 +246,7 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do
fi
if ((${#AUTH_FILES[@]} > 0)); then
for auth_file in "${AUTH_FILES[@]}"; do
auth_file="$(openclaw_live_validate_relative_home_path "$auth_file")"
host_path="$HOME/$auth_file"
if [[ -f "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth-files/"$auth_file":ro)
@@ -246,18 +265,22 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do
-e ANTHROPIC_API_KEY_OLD \
-e OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}" \
-e OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY_OLD="${ANTHROPIC_API_KEY_OLD:-}" \
-e GEMINI_API_KEY \
-e GOOGLE_API_KEY \
-e OPENAI_API_KEY \
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
-e HOME=/home/node \
-e NODE_OPTIONS=--disable-warning=ExperimentalWarning \
-e OPENCLAW_SKIP_CHANNELS=1 \
-e OPENCLAW_VITEST_FS_MODULE_CACHE=0 \
-e OPENCLAW_DOCKER_AUTH_PRESTAGED="$DOCKER_AUTH_PRESTAGED" \
-e OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED="$AUTH_DIRS_CSV" \
-e OPENCLAW_DOCKER_AUTH_FILES_RESOLVED="$AUTH_FILES_CSV" \
-e OPENCLAW_LIVE_TEST=1 \
-e OPENCLAW_LIVE_ACP_BIND=1 \
-e OPENCLAW_LIVE_ACP_BIND_AGENT="$ACP_AGENT" \
-e OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND="$AGENT_COMMAND" \
"${DOCKER_HOME_MOUNT[@]}" \
-v "$CACHE_HOME_DIR":/home/node/.cache \
-v "$ROOT_DIR":/src:ro \
-v "$CONFIG_DIR":/home/node/.openclaw \

View File

@@ -15,6 +15,9 @@ CLI_DISABLE_MCP_CONFIG="${OPENCLAW_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG:-}"
CLI_AUTH_MODE="${OPENCLAW_LIVE_CLI_BACKEND_AUTH:-auto}"
TEMP_DIRS=()
DOCKER_USER="${OPENCLAW_DOCKER_USER:-node}"
DOCKER_HOME_MOUNT=()
DOCKER_EXTRA_ENV_FILES=()
DOCKER_AUTH_PRESTAGED=0
if [[ -z "$CLI_PROVIDER" || "$CLI_PROVIDER" == "$CLI_MODEL" ]]; then
CLI_PROVIDER="$DEFAULT_PROVIDER"
@@ -34,6 +37,13 @@ if [[ "$CLI_AUTH_MODE" == "subscription" && "$CLI_PROVIDER" != "claude-cli" ]];
exit 1
fi
if [[ "$CLI_AUTH_MODE" == "api-key" && "$CLI_PROVIDER" == "codex-cli" ]]; then
if [[ -z "${OPENAI_API_KEY:-}" ]]; then
echo "ERROR: OPENCLAW_LIVE_CLI_BACKEND_AUTH=api-key for codex-cli requires OPENAI_API_KEY." >&2
exit 1
fi
fi
CLI_METADATA_JSON="$(node --import tsx "$ROOT_DIR/scripts/print-cli-backend-live-metadata.ts" "$CLI_PROVIDER")"
read_metadata_field() {
local field="$1"
@@ -84,6 +94,9 @@ mkdir -p "$CLI_TOOLS_DIR"
mkdir -p "$CACHE_HOME_DIR"
if [[ "${CI:-}" == "true" || "${GITHUB_ACTIONS:-}" == "true" ]]; then
DOCKER_USER="$(id -u):$(id -g)"
DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")"
TEMP_DIRS+=("$DOCKER_HOME_DIR")
DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node)
fi
if [[ "$CLI_PROVIDER" == "claude-cli" && "$CLI_AUTH_MODE" == "subscription" ]]; then
@@ -143,7 +156,9 @@ fi
AUTH_DIRS=()
AUTH_FILES=()
if [[ -n "${OPENCLAW_DOCKER_AUTH_DIRS:-}" ]]; then
if [[ "$CLI_AUTH_MODE" == "api-key" && "$CLI_PROVIDER" == "codex-cli" ]]; then
AUTH_FILES+=(".codex/config.toml")
elif [[ -n "${OPENCLAW_DOCKER_AUTH_DIRS:-}" ]]; then
while IFS= read -r auth_dir; do
[[ -n "$auth_dir" ]] || continue
AUTH_DIRS+=("$auth_dir")
@@ -171,9 +186,15 @@ if ((${#AUTH_FILES[@]} > 0)); then
AUTH_FILES_CSV="$(openclaw_live_join_csv "${AUTH_FILES[@]}")"
fi
if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then
openclaw_live_stage_auth_into_home "$DOCKER_HOME_DIR" "${AUTH_DIRS[@]}" --files "${AUTH_FILES[@]}"
DOCKER_AUTH_PRESTAGED=1
fi
EXTERNAL_AUTH_MOUNTS=()
if ((${#AUTH_DIRS[@]} > 0)); then
for auth_dir in "${AUTH_DIRS[@]}"; do
auth_dir="$(openclaw_live_validate_relative_home_path "$auth_dir")"
host_path="$HOME/$auth_dir"
if [[ -d "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth/"$auth_dir":ro)
@@ -182,6 +203,7 @@ if ((${#AUTH_DIRS[@]} > 0)); then
fi
if ((${#AUTH_FILES[@]} > 0)); then
for auth_file in "${AUTH_FILES[@]}"; do
auth_file="$(openclaw_live_validate_relative_home_path "$auth_file")"
host_path="$HOME/$auth_file"
if [[ -f "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth-files/"$auth_file":ro)
@@ -201,27 +223,29 @@ export npm_config_cache="$NPM_CONFIG_CACHE"
mkdir -p "$NPM_CONFIG_PREFIX" "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE"
chmod 700 "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE" || true
export PATH="$NPM_CONFIG_PREFIX/bin:$PATH"
IFS=',' read -r -a auth_dirs <<<"${OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED:-}"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_dirs[@]} > 0)); then
for auth_dir in "${auth_dirs[@]}"; do
[ -n "$auth_dir" ] || continue
if [ -d "/host-auth/$auth_dir" ]; then
mkdir -p "$HOME/$auth_dir"
cp -R "/host-auth/$auth_dir/." "$HOME/$auth_dir"
chmod -R u+rwX "$HOME/$auth_dir" || true
fi
done
fi
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
if [ "${OPENCLAW_DOCKER_AUTH_PRESTAGED:-0}" != "1" ]; then
IFS=',' read -r -a auth_dirs <<<"${OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED:-}"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_dirs[@]} > 0)); then
for auth_dir in "${auth_dirs[@]}"; do
[ -n "$auth_dir" ] || continue
if [ -d "/host-auth/$auth_dir" ]; then
mkdir -p "$HOME/$auth_dir"
cp -R "/host-auth/$auth_dir/." "$HOME/$auth_dir"
chmod -R u+rwX "$HOME/$auth_dir" || true
fi
done
fi
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
fi
fi
provider="${OPENCLAW_DOCKER_CLI_BACKEND_PROVIDER:-claude-cli}"
default_command="${OPENCLAW_DOCKER_CLI_BACKEND_COMMAND_DEFAULT:-}"
@@ -236,6 +260,17 @@ fi
if [ -n "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:-}" ] && [ ! -x "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}" ] && [ -n "$docker_package" ]; then
npm install -g "$docker_package"
fi
if [ "$provider" = "codex-cli" ] && [ "${OPENCLAW_LIVE_CLI_BACKEND_AUTH:-auto}" = "api-key" ]; then
codex_login_command="${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:-$NPM_CONFIG_PREFIX/bin/codex}"
if [ ! -x "$codex_login_command" ] && [ -x "$NPM_CONFIG_PREFIX/bin/codex" ]; then
codex_login_command="$NPM_CONFIG_PREFIX/bin/codex"
fi
printf '%s\n' "$OPENAI_API_KEY" | "$codex_login_command" login --with-api-key >/dev/null
fi
if [ -n "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:-}" ] && [ -x "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}" ]; then
echo "==> CLI backend binary: ${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}"
"${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}" -V || "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}" --version || true
fi
if [ "$provider" = "claude-cli" ]; then
auth_mode="${OPENCLAW_LIVE_CLI_BACKEND_AUTH:-auto}"
if [ "$auth_mode" = "subscription" ]; then
@@ -324,6 +359,9 @@ openclaw_live_link_runtime_tree "$tmp_dir"
openclaw_live_stage_state_dir "$tmp_dir/.openclaw-state"
openclaw_live_prepare_staged_config
cd "$tmp_dir"
if [ "${OPENCLAW_LIVE_CLI_BACKEND_USE_CI_SAFE_CODEX_CONFIG:-0}" = "1" ]; then
node --import tsx /src/scripts/prepare-codex-ci-config.ts "$HOME/.codex/config.toml" "$tmp_dir"
fi
pnpm test:live src/gateway/gateway-cli-backend.live.test.ts
EOF
@@ -346,7 +384,18 @@ echo "==> External auth files: ${AUTH_FILES_CSV:-none}"
DOCKER_AUTH_ENV=(
-e OPENCLAW_LIVE_CLI_BACKEND_AUTH="$CLI_AUTH_MODE"
)
if [[ "$CLI_PROVIDER" == "claude-cli" && "$CLI_AUTH_MODE" == "subscription" ]]; then
if [[ "$CLI_PROVIDER" == "codex-cli" && "$CLI_AUTH_MODE" == "api-key" ]]; then
docker_env_dir="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-cli-backend-env.XXXXXX")"
TEMP_DIRS+=("$docker_env_dir")
docker_env_file="$docker_env_dir/openai.env"
{
printf 'OPENAI_API_KEY=%s\n' "${OPENAI_API_KEY}"
if [[ -n "${OPENAI_BASE_URL:-}" ]]; then
printf 'OPENAI_BASE_URL=%s\n' "${OPENAI_BASE_URL}"
fi
} >"$docker_env_file"
DOCKER_EXTRA_ENV_FILES+=(--env-file "$docker_env_file")
elif [[ "$CLI_PROVIDER" == "claude-cli" && "$CLI_AUTH_MODE" == "subscription" ]]; then
DOCKER_AUTH_ENV+=(
-e CLAUDE_CODE_OAUTH_TOKEN="${CLAUDE_CODE_OAUTH_TOKEN:-}"
-e OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV="$OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV"
@@ -369,8 +418,10 @@ docker run --rm -t \
-e NODE_OPTIONS=--disable-warning=ExperimentalWarning \
-e OPENCLAW_SKIP_CHANNELS=1 \
-e OPENCLAW_VITEST_FS_MODULE_CACHE=0 \
-e OPENCLAW_DOCKER_AUTH_PRESTAGED="$DOCKER_AUTH_PRESTAGED" \
-e OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED="$AUTH_DIRS_CSV" \
-e OPENCLAW_DOCKER_AUTH_FILES_RESOLVED="$AUTH_FILES_CSV" \
-e OPENCLAW_LIVE_CLI_BACKEND_USE_CI_SAFE_CODEX_CONFIG="${OPENCLAW_LIVE_CLI_BACKEND_USE_CI_SAFE_CODEX_CONFIG:-0}" \
-e OPENCLAW_DOCKER_CLI_BACKEND_PROVIDER="$CLI_PROVIDER" \
-e OPENCLAW_DOCKER_CLI_BACKEND_COMMAND_DEFAULT="$CLI_DEFAULT_COMMAND" \
-e OPENCLAW_DOCKER_CLI_BACKEND_NPM_PACKAGE="$CLI_DOCKER_NPM_PACKAGE" \
@@ -382,6 +433,7 @@ docker run --rm -t \
-e OPENCLAW_LIVE_CLI_BACKEND_MODEL="$CLI_MODEL" \
-e OPENCLAW_LIVE_CLI_BACKEND_COMMAND="${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:-}" \
-e OPENCLAW_LIVE_CLI_BACKEND_ARGS="${OPENCLAW_LIVE_CLI_BACKEND_ARGS:-}" \
-e OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS="${OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS:-}" \
-e OPENCLAW_LIVE_CLI_BACKEND_CLEAR_ENV="${OPENCLAW_LIVE_CLI_BACKEND_CLEAR_ENV:-}" \
-e OPENCLAW_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG="$CLI_DISABLE_MCP_CONFIG" \
-e OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE:-}" \
@@ -390,6 +442,8 @@ docker run --rm -t \
-e OPENCLAW_LIVE_CLI_BACKEND_MCP_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_MCP_PROBE:-}" \
-e OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="${OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG:-}" \
-e OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="${OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE:-}" \
"${DOCKER_HOME_MOUNT[@]}" \
"${DOCKER_EXTRA_ENV_FILES[@]}" \
-v "$CACHE_HOME_DIR":/home/node/.cache \
-v "$ROOT_DIR":/src:ro \
-v "$CONFIG_DIR":/home/node/.openclaw \

View File

@@ -8,8 +8,26 @@ LIVE_IMAGE_NAME="${OPENCLAW_LIVE_IMAGE:-${IMAGE_NAME}-live}"
CONFIG_DIR="${OPENCLAW_CONFIG_DIR:-$HOME/.openclaw}"
WORKSPACE_DIR="${OPENCLAW_WORKSPACE_DIR:-$HOME/.openclaw/workspace}"
PROFILE_FILE="${OPENCLAW_PROFILE_FILE:-$HOME/.profile}"
CODEX_HARNESS_AUTH_MODE="${OPENCLAW_LIVE_CODEX_HARNESS_AUTH:-codex-auth}"
TEMP_DIRS=()
DOCKER_USER="${OPENCLAW_DOCKER_USER:-node}"
DOCKER_HOME_MOUNT=()
DOCKER_EXTRA_ENV_FILES=()
DOCKER_AUTH_PRESTAGED=0
case "$CODEX_HARNESS_AUTH_MODE" in
codex-auth | api-key)
;;
*)
echo "ERROR: OPENCLAW_LIVE_CODEX_HARNESS_AUTH must be one of: codex-auth, api-key." >&2
exit 1
;;
esac
if [[ "$CODEX_HARNESS_AUTH_MODE" == "api-key" && -z "${OPENAI_API_KEY:-}" ]]; then
echo "ERROR: OPENCLAW_LIVE_CODEX_HARNESS_AUTH=api-key requires OPENAI_API_KEY." >&2
exit 1
fi
cleanup_temp_dirs() {
if ((${#TEMP_DIRS[@]} > 0)); then
@@ -39,6 +57,9 @@ mkdir -p "$CLI_TOOLS_DIR"
mkdir -p "$CACHE_HOME_DIR"
if [[ "${CI:-}" == "true" || "${GITHUB_ACTIONS:-}" == "true" ]]; then
DOCKER_USER="$(id -u):$(id -g)"
DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")"
TEMP_DIRS+=("$DOCKER_HOME_DIR")
DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node)
fi
PROFILE_MOUNT=()
@@ -47,19 +68,27 @@ if [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then
fi
AUTH_FILES=()
while IFS= read -r auth_file; do
[[ -n "$auth_file" ]] || continue
AUTH_FILES+=("$auth_file")
done < <(openclaw_live_collect_auth_files_from_csv "openai-codex")
if [[ "$CODEX_HARNESS_AUTH_MODE" != "api-key" ]]; then
while IFS= read -r auth_file; do
[[ -n "$auth_file" ]] || continue
AUTH_FILES+=("$auth_file")
done < <(openclaw_live_collect_auth_files_from_csv "openai-codex")
fi
AUTH_FILES_CSV=""
if ((${#AUTH_FILES[@]} > 0)); then
AUTH_FILES_CSV="$(openclaw_live_join_csv "${AUTH_FILES[@]}")"
fi
if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then
openclaw_live_stage_auth_into_home "$DOCKER_HOME_DIR" --files "${AUTH_FILES[@]}"
DOCKER_AUTH_PRESTAGED=1
fi
EXTERNAL_AUTH_MOUNTS=()
if ((${#AUTH_FILES[@]} > 0)); then
for auth_file in "${AUTH_FILES[@]}"; do
auth_file="$(openclaw_live_validate_relative_home_path "$auth_file")"
host_path="$HOME/$auth_file"
if [[ -f "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth-files/"$auth_file":ro)
@@ -67,6 +96,20 @@ if ((${#AUTH_FILES[@]} > 0)); then
done
fi
DOCKER_AUTH_ENV=()
if [[ "$CODEX_HARNESS_AUTH_MODE" == "api-key" ]]; then
docker_env_dir="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-codex-harness-env.XXXXXX")"
TEMP_DIRS+=("$docker_env_dir")
docker_env_file="$docker_env_dir/openai.env"
{
printf 'OPENAI_API_KEY=%s\n' "${OPENAI_API_KEY}"
if [[ -n "${OPENAI_BASE_URL:-}" ]]; then
printf 'OPENAI_BASE_URL=%s\n' "${OPENAI_BASE_URL}"
fi
} >"$docker_env_file"
DOCKER_EXTRA_ENV_FILES+=(--env-file "$docker_env_file")
fi
read -r -d '' LIVE_TEST_CMD <<'EOF' || true
set -euo pipefail
[ -f "$HOME/.profile" ] && [ -r "$HOME/.profile" ] && source "$HOME/.profile" || true
@@ -76,23 +119,38 @@ export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
export COREPACK_HOME="${COREPACK_HOME:-$XDG_CACHE_HOME/node/corepack}"
export NPM_CONFIG_CACHE="${NPM_CONFIG_CACHE:-$XDG_CACHE_HOME/npm}"
export npm_config_cache="$NPM_CONFIG_CACHE"
# Force the Codex harness to use the staged `~/.codex` auth files. This lane
# is not meant to exercise raw OpenAI API-key routing unless the lane
# explicitly opts into API-key auth for CI.
if [ "${OPENCLAW_LIVE_CODEX_HARNESS_AUTH:-codex-auth}" != "api-key" ]; then
unset OPENAI_API_KEY OPENAI_BASE_URL
fi
mkdir -p "$NPM_CONFIG_PREFIX" "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE"
chmod 700 "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE" || true
export PATH="$NPM_CONFIG_PREFIX/bin:$PATH"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
if [ "${OPENCLAW_DOCKER_AUTH_PRESTAGED:-0}" != "1" ]; then
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
fi
fi
if [ "${OPENCLAW_LIVE_CODEX_HARNESS_AUTH:-codex-auth}" != "api-key" ] && [ ! -s "$HOME/.codex/auth.json" ]; then
echo "ERROR: missing ~/.codex/auth.json for Codex harness live test." >&2
exit 1
fi
if [ ! -x "$NPM_CONFIG_PREFIX/bin/codex" ]; then
npm install -g @openai/codex
fi
if [ "${OPENCLAW_LIVE_CODEX_HARNESS_AUTH:-codex-auth}" = "api-key" ]; then
printf '%s\n' "$OPENAI_API_KEY" | "$NPM_CONFIG_PREFIX/bin/codex" login --with-api-key >/dev/null
fi
tmp_dir="$(mktemp -d)"
cleanup() {
rm -rf "$tmp_dir"
@@ -117,6 +175,7 @@ echo "==> Run Codex harness live test in Docker"
echo "==> Model: ${OPENCLAW_LIVE_CODEX_HARNESS_MODEL:-codex/gpt-5.4}"
echo "==> Image probe: ${OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE:-1}"
echo "==> MCP probe: ${OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE:-1}"
echo "==> Auth mode: $CODEX_HARNESS_AUTH_MODE"
echo "==> Harness fallback: none"
echo "==> Auth files: ${AUTH_FILES_CSV:-none}"
docker run --rm -t \
@@ -125,10 +184,11 @@ docker run --rm -t \
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
-e HOME=/home/node \
-e NODE_OPTIONS=--disable-warning=ExperimentalWarning \
-e OPENAI_API_KEY \
-e OPENCLAW_AGENT_HARNESS_FALLBACK=none \
-e OPENCLAW_DOCKER_AUTH_PRESTAGED="$DOCKER_AUTH_PRESTAGED" \
-e OPENCLAW_CODEX_APP_SERVER_BIN="${OPENCLAW_CODEX_APP_SERVER_BIN:-codex}" \
-e OPENCLAW_DOCKER_AUTH_FILES_RESOLVED="$AUTH_FILES_CSV" \
-e OPENCLAW_LIVE_CODEX_HARNESS_AUTH="$CODEX_HARNESS_AUTH_MODE" \
-e OPENCLAW_LIVE_CODEX_HARNESS=1 \
-e OPENCLAW_LIVE_CODEX_HARNESS_DEBUG="${OPENCLAW_LIVE_CODEX_HARNESS_DEBUG:-}" \
-e OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE="${OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE:-1}" \
@@ -136,6 +196,9 @@ docker run --rm -t \
-e OPENCLAW_LIVE_CODEX_HARNESS_MODEL="${OPENCLAW_LIVE_CODEX_HARNESS_MODEL:-codex/gpt-5.4}" \
-e OPENCLAW_LIVE_TEST=1 \
-e OPENCLAW_VITEST_FS_MODULE_CACHE=0 \
"${DOCKER_AUTH_ENV[@]}" \
"${DOCKER_EXTRA_ENV_FILES[@]}" \
"${DOCKER_HOME_MOUNT[@]}" \
-v "$CACHE_HOME_DIR":/home/node/.cache \
-v "$ROOT_DIR":/src:ro \
-v "$CONFIG_DIR":/home/node/.openclaw \

View File

@@ -10,6 +10,8 @@ WORKSPACE_DIR="${OPENCLAW_WORKSPACE_DIR:-$HOME/.openclaw/workspace}"
PROFILE_FILE="${OPENCLAW_PROFILE_FILE:-$HOME/.profile}"
DOCKER_USER="${OPENCLAW_DOCKER_USER:-node}"
TEMP_DIRS=()
DOCKER_HOME_MOUNT=()
DOCKER_AUTH_PRESTAGED=0
cleanup_temp_dirs() {
if ((${#TEMP_DIRS[@]} > 0)); then
rm -rf "${TEMP_DIRS[@]}"
@@ -27,6 +29,9 @@ fi
mkdir -p "$CACHE_HOME_DIR"
if [[ "${CI:-}" == "true" || "${GITHUB_ACTIONS:-}" == "true" ]]; then
DOCKER_USER="$(id -u):$(id -g)"
DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")"
TEMP_DIRS+=("$DOCKER_HOME_DIR")
DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node)
fi
PROFILE_MOUNT=()
@@ -73,9 +78,15 @@ if ((${#AUTH_FILES[@]} > 0)); then
AUTH_FILES_CSV="$(openclaw_live_join_csv "${AUTH_FILES[@]}")"
fi
if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then
openclaw_live_stage_auth_into_home "$DOCKER_HOME_DIR" "${AUTH_DIRS[@]}" --files "${AUTH_FILES[@]}"
DOCKER_AUTH_PRESTAGED=1
fi
EXTERNAL_AUTH_MOUNTS=()
if ((${#AUTH_DIRS[@]} > 0)); then
for auth_dir in "${AUTH_DIRS[@]}"; do
auth_dir="$(openclaw_live_validate_relative_home_path "$auth_dir")"
host_path="$HOME/$auth_dir"
if [[ -d "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth/"$auth_dir":ro)
@@ -84,6 +95,7 @@ if ((${#AUTH_DIRS[@]} > 0)); then
fi
if ((${#AUTH_FILES[@]} > 0)); then
for auth_file in "${AUTH_FILES[@]}"; do
auth_file="$(openclaw_live_validate_relative_home_path "$auth_file")"
host_path="$HOME/$auth_file"
if [[ -f "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth-files/"$auth_file":ro)
@@ -100,27 +112,29 @@ export NPM_CONFIG_CACHE="${NPM_CONFIG_CACHE:-$XDG_CACHE_HOME/npm}"
export npm_config_cache="$NPM_CONFIG_CACHE"
mkdir -p "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE"
chmod 700 "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE" || true
IFS=',' read -r -a auth_dirs <<<"${OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED:-}"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_dirs[@]} > 0)); then
for auth_dir in "${auth_dirs[@]}"; do
[ -n "$auth_dir" ] || continue
if [ -d "/host-auth/$auth_dir" ]; then
mkdir -p "$HOME/$auth_dir"
cp -R "/host-auth/$auth_dir/." "$HOME/$auth_dir"
chmod -R u+rwX "$HOME/$auth_dir" || true
fi
done
fi
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
if [ "${OPENCLAW_DOCKER_AUTH_PRESTAGED:-0}" != "1" ]; then
IFS=',' read -r -a auth_dirs <<<"${OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED:-}"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_dirs[@]} > 0)); then
for auth_dir in "${auth_dirs[@]}"; do
[ -n "$auth_dir" ] || continue
if [ -d "/host-auth/$auth_dir" ]; then
mkdir -p "$HOME/$auth_dir"
cp -R "/host-auth/$auth_dir/." "$HOME/$auth_dir"
chmod -R u+rwX "$HOME/$auth_dir" || true
fi
done
fi
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
fi
fi
tmp_dir="$(mktemp -d)"
cleanup() {
@@ -154,6 +168,7 @@ docker run --rm -t \
-e NODE_OPTIONS=--disable-warning=ExperimentalWarning \
-e OPENCLAW_SKIP_CHANNELS=1 \
-e OPENCLAW_SUPPRESS_NOTES=1 \
-e OPENCLAW_DOCKER_AUTH_PRESTAGED="$DOCKER_AUTH_PRESTAGED" \
-e OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED="$AUTH_DIRS_CSV" \
-e OPENCLAW_DOCKER_AUTH_FILES_RESOLVED="$AUTH_FILES_CSV" \
-e OPENCLAW_LIVE_TEST=1 \
@@ -163,6 +178,7 @@ docker run --rm -t \
-e OPENCLAW_LIVE_GATEWAY_MAX_MODELS="${OPENCLAW_LIVE_GATEWAY_MAX_MODELS:-8}" \
-e OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS="${OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS:-45000}" \
-e OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS="${OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS:-90000}" \
"${DOCKER_HOME_MOUNT[@]}" \
-v "$CACHE_HOME_DIR":/home/node/.cache \
-v "$ROOT_DIR":/src:ro \
-v "$CONFIG_DIR":/home/node/.openclaw \

View File

@@ -7,6 +7,7 @@ IMAGE_NAME="${OPENCLAW_IMAGE:-openclaw:local}"
LIVE_IMAGE_NAME="${OPENCLAW_LIVE_IMAGE:-${IMAGE_NAME}-live}"
PROFILE_FILE="${OPENCLAW_PROFILE_FILE:-$HOME/.profile}"
DOCKER_USER="${OPENCLAW_DOCKER_USER:-node}"
DOCKER_AUTH_PRESTAGED=0
openclaw_live_truthy() {
case "${1:-}" in
@@ -20,6 +21,7 @@ openclaw_live_truthy() {
}
TEMP_DIRS=()
DOCKER_HOME_MOUNT=()
cleanup_temp_dirs() {
if ((${#TEMP_DIRS[@]} > 0)); then
rm -rf "${TEMP_DIRS[@]}"
@@ -47,6 +49,9 @@ fi
mkdir -p "$CACHE_HOME_DIR"
if [[ "${CI:-}" == "true" || "${GITHUB_ACTIONS:-}" == "true" ]]; then
DOCKER_USER="$(id -u):$(id -g)"
DOCKER_HOME_DIR="$(mktemp -d "${RUNNER_TEMP:-/tmp}/openclaw-docker-home.XXXXXX")"
TEMP_DIRS+=("$DOCKER_HOME_DIR")
DOCKER_HOME_MOUNT=(-v "$DOCKER_HOME_DIR":/home/node)
fi
PROFILE_MOUNT=()
@@ -103,9 +108,15 @@ if ((${#AUTH_FILES[@]} > 0)); then
AUTH_FILES_CSV="$(openclaw_live_join_csv "${AUTH_FILES[@]}")"
fi
if [[ -n "${DOCKER_HOME_DIR:-}" ]]; then
openclaw_live_stage_auth_into_home "$DOCKER_HOME_DIR" "${AUTH_DIRS[@]}" --files "${AUTH_FILES[@]}"
DOCKER_AUTH_PRESTAGED=1
fi
EXTERNAL_AUTH_MOUNTS=()
if ((${#AUTH_DIRS[@]} > 0)); then
for auth_dir in "${AUTH_DIRS[@]}"; do
auth_dir="$(openclaw_live_validate_relative_home_path "$auth_dir")"
host_path="$HOME/$auth_dir"
if [[ -d "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth/"$auth_dir":ro)
@@ -114,6 +125,7 @@ if ((${#AUTH_DIRS[@]} > 0)); then
fi
if ((${#AUTH_FILES[@]} > 0)); then
for auth_file in "${AUTH_FILES[@]}"; do
auth_file="$(openclaw_live_validate_relative_home_path "$auth_file")"
host_path="$HOME/$auth_file"
if [[ -f "$host_path" ]]; then
EXTERNAL_AUTH_MOUNTS+=(-v "$host_path":/host-auth-files/"$auth_file":ro)
@@ -130,27 +142,29 @@ export NPM_CONFIG_CACHE="${NPM_CONFIG_CACHE:-$XDG_CACHE_HOME/npm}"
export npm_config_cache="$NPM_CONFIG_CACHE"
mkdir -p "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE"
chmod 700 "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE" || true
IFS=',' read -r -a auth_dirs <<<"${OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED:-}"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_dirs[@]} > 0)); then
for auth_dir in "${auth_dirs[@]}"; do
[ -n "$auth_dir" ] || continue
if [ -d "/host-auth/$auth_dir" ]; then
mkdir -p "$HOME/$auth_dir"
cp -R "/host-auth/$auth_dir/." "$HOME/$auth_dir"
chmod -R u+rwX "$HOME/$auth_dir" || true
fi
done
fi
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
if [ "${OPENCLAW_DOCKER_AUTH_PRESTAGED:-0}" != "1" ]; then
IFS=',' read -r -a auth_dirs <<<"${OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED:-}"
IFS=',' read -r -a auth_files <<<"${OPENCLAW_DOCKER_AUTH_FILES_RESOLVED:-}"
if ((${#auth_dirs[@]} > 0)); then
for auth_dir in "${auth_dirs[@]}"; do
[ -n "$auth_dir" ] || continue
if [ -d "/host-auth/$auth_dir" ]; then
mkdir -p "$HOME/$auth_dir"
cp -R "/host-auth/$auth_dir/." "$HOME/$auth_dir"
chmod -R u+rwX "$HOME/$auth_dir" || true
fi
done
fi
if ((${#auth_files[@]} > 0)); then
for auth_file in "${auth_files[@]}"; do
[ -n "$auth_file" ] || continue
if [ -f "/host-auth-files/$auth_file" ]; then
mkdir -p "$(dirname "$HOME/$auth_file")"
cp "/host-auth-files/$auth_file" "$HOME/$auth_file"
chmod u+rw "$HOME/$auth_file" || true
fi
done
fi
fi
tmp_dir="$(mktemp -d)"
cleanup() {
@@ -185,6 +199,7 @@ docker run --rm -t \
-e NODE_OPTIONS=--disable-warning=ExperimentalWarning \
-e OPENCLAW_SKIP_CHANNELS=1 \
-e OPENCLAW_SUPPRESS_NOTES=1 \
-e OPENCLAW_DOCKER_AUTH_PRESTAGED="$DOCKER_AUTH_PRESTAGED" \
-e OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED="$AUTH_DIRS_CSV" \
-e OPENCLAW_DOCKER_AUTH_FILES_RESOLVED="$AUTH_FILES_CSV" \
-e OPENCLAW_LIVE_TEST=1 \
@@ -196,6 +211,7 @@ docker run --rm -t \
-e OPENCLAW_LIVE_GATEWAY_MODELS="${OPENCLAW_LIVE_GATEWAY_MODELS:-}" \
-e OPENCLAW_LIVE_GATEWAY_PROVIDERS="${OPENCLAW_LIVE_GATEWAY_PROVIDERS:-}" \
-e OPENCLAW_LIVE_GATEWAY_MAX_MODELS="${OPENCLAW_LIVE_GATEWAY_MAX_MODELS:-}" \
"${DOCKER_HOME_MOUNT[@]}" \
-v "$CACHE_HOME_DIR":/home/node/.cache \
-v "$ROOT_DIR":/src:ro \
-v "$CONFIG_DIR":/home/node/.openclaw \