openclaw/scripts/e2e/cli-installer-distribution-docker.sh
Josh Avant 6c00e67f57
fix(security): require patched Node and native pnpm runtimes (#179992)
* fix(runtime): require Node releases that reject compromised CA keys

Require Node 24.22.1 or 26.12.1 even when SQLite capability checks pass.
Align active managed runtime selectors, archive checksums, image digests, native macOS selection, diagnostics, and coupled fixtures while preserving update recovery.

* fix(tooling): use pnpm that rejects compromised CA keys

* test(runtime): align pinned Node fixtures and generated guidance

* test(runtime): qualify service and update fixtures at patched Node floor

* fix(security): update Alpine test trust and aligned workflow contracts

* test: align guest runtime fixture and preserve mock exports
2026-10-21 21:00:53 -07:00

160 lines
5.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# Bash 5.3+ can deadlock writing heredoc pipes on macOS before the reader starts.
if [[ ${OSTYPE:-} == darwin* && $BASH != /bin/bash ]] && ((BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3))); then
exec /bin/bash "$0" "$@"
fi
# Proves hosted npm installation plus dedicated-prefix source installation.
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SOURCE_ROOT="${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$ROOT_DIR}"
source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-cli-installer-distribution:local")"
PACKAGE_TGZ="$(
docker_e2e_prepare_package_tgz cli-installer-distribution "${OPENCLAW_CURRENT_PACKAGE_TGZ:-}"
)"
docker_e2e_package_mount_args "$PACKAGE_TGZ"
HOSTED_PROOF_CONTAINER="openclaw-hosted-installer-proof-$$"
SOURCE_PROOF_CONTAINER="openclaw-source-installer-proof-$$"
SOURCE_BUNDLE="$(mktemp "${TMPDIR:-/tmp}/openclaw-source.XXXXXX.bundle")"
SOURCE_PROOF_SCRIPT="$(mktemp "${TMPDIR:-/tmp}/openclaw-source-proof.XXXXXX.sh")"
SOURCE_SHA="$(git -C "$SOURCE_ROOT" rev-parse HEAD)"
SOURCE_MEMORY="${OPENCLAW_CLI_INSTALLER_SOURCE_MEMORY:-16g}"
INSTALLERS_DIR=""
cleanup() {
docker_e2e_docker_cmd rm -f \
"$HOSTED_PROOF_CONTAINER" \
"$SOURCE_PROOF_CONTAINER" >/dev/null 2>&1 || true
docker_e2e_cleanup_package_tgz "$PACKAGE_TGZ"
rm -f "$SOURCE_BUNDLE" "$SOURCE_PROOF_SCRIPT"
[[ -z "$INSTALLERS_DIR" ]] || rm -rf "$INSTALLERS_DIR"
}
trap cleanup EXIT
git -C "$SOURCE_ROOT" bundle create "$SOURCE_BUNDLE" HEAD
cat >"$SOURCE_PROOF_SCRIPT" <<'SOURCE_PROOF'
#!/usr/bin/env bash
set -euo pipefail
test -r "$0"
test -x "$0"
command -v curl >/dev/null
git clone -q /tmp/openclaw-source.bundle /tmp/openclaw-source
git -C /tmp/openclaw-source checkout -q --detach "$OPENCLAW_SOURCE_SHA"
bash /tmp/openclaw-source/scripts/install-cli.sh \
--install-method git \
--git-dir /tmp/openclaw-source \
--version "$OPENCLAW_SOURCE_SHA" \
--no-git-update \
--prefix /tmp/openclaw-prefix \
--node-version 24.22.1 \
--no-onboard
prefix_node=/tmp/openclaw-prefix/tools/node/bin/node
prefix_cli=/tmp/openclaw-prefix/bin/openclaw
test -x "$prefix_node"
test -x "$prefix_cli"
grep -Fq "exec \"$prefix_node\"" "$prefix_cli"
grep -Fq "/tmp/openclaw-source/dist/entry.js" "$prefix_cli"
export PATH="/tmp/openclaw-prefix/bin:$PATH"
test "$(command -v openclaw)" = "$prefix_cli"
test "$(git -C /tmp/openclaw-source rev-parse HEAD)" = "$OPENCLAW_SOURCE_SHA"
openclaw_version="$(openclaw --version)"
openclaw --help >/tmp/openclaw-help
test -s /tmp/openclaw-help
status_json="$(openclaw update status --json)"
STATUS_JSON="$status_json" node -e "
const status = JSON.parse(process.env.STATUS_JSON);
if (status.update?.installKind !== \"git\") {
throw new Error(\`expected git install kind, got \${status.update?.installKind}\`);
}
"
printf "prefixNode=%s@%s\n" "$prefix_node" "$("$prefix_node" --version)"
printf "prefixOpenClaw=%s@%s\n" "$prefix_cli" "$openclaw_version"
printf "sourceHead=%s installKind=git\n" "$OPENCLAW_SOURCE_SHA"
printf "sourceOnboard=disabled\n"
touch /tmp/openclaw-proof-ready
exec sleep infinity
SOURCE_PROOF
chmod 0555 "$SOURCE_PROOF_SCRIPT"
docker_e2e_build_or_reuse \
"$IMAGE_NAME" \
cli-installer-distribution \
"$ROOT_DIR/scripts/e2e/Dockerfile" \
"$ROOT_DIR" \
bare
INSTALLERS_DIR="$(mktemp -d "${TMPDIR:-/tmp}/openclaw-installers.XXXXXX")"
node "$ROOT_DIR/scripts/build-installers.mjs" "$INSTALLERS_DIR" "$SOURCE_ROOT"
echo "==> Hosted install.sh exact-candidate proof"
docker_e2e_docker_run_cmd run -d \
--name "$HOSTED_PROOF_CONTAINER" \
-e HOME=/tmp/openclaw-hosted-home \
-e OPENCLAW_NO_ONBOARD=1 \
-e OPENCLAW_NO_PROMPT=1 \
"${DOCKER_E2E_PACKAGE_ARGS[@]}" \
-v "$INSTALLERS_DIR/install.sh:/tmp/install.sh:ro" \
"$IMAGE_NAME" \
bash -lc '
set -euo pipefail
mkdir -p "$HOME"
bash /tmp/install.sh \
--install-method npm \
--version file:/tmp/openclaw-current.tgz \
--no-onboard \
--no-prompt
source "$HOME/.bashrc"
hash -r
openclaw_path="$(command -v openclaw)"
test -n "$openclaw_path"
node_path="$(command -v node)"
node_version="$(node --version)"
openclaw_version="$(openclaw --version)"
openclaw --help >/tmp/openclaw-help
test -s /tmp/openclaw-help
printf "hostedNode=%s@%s\n" "$node_path" "$node_version"
printf "hostedOpenClaw=%s@%s\n" "$openclaw_path" "$openclaw_version"
printf "hostedOnboard=disabled\n"
touch /tmp/openclaw-proof-ready
exec sleep infinity
' >/dev/null
# A full source install builds every workspace package; the shared 8g cap OOMs before wrapper creation.
echo "==> install-cli.sh dedicated-prefix source-checkout proof"
docker_e2e_docker_run_cmd run -d \
--name "$SOURCE_PROOF_CONTAINER" \
--memory "$SOURCE_MEMORY" \
-e HOME=/tmp/openclaw-source-home \
-e OPENCLAW_NO_ONBOARD=1 \
-e OPENCLAW_NO_PROMPT=1 \
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
-e "OPENCLAW_SOURCE_SHA=$SOURCE_SHA" \
--user root \
-v "$SOURCE_BUNDLE:/tmp/openclaw-source.bundle:ro" \
-v "$SOURCE_PROOF_SCRIPT:/tmp/source-proof.sh:ro" \
"$IMAGE_NAME" \
bash -lc '
set -euo pipefail
rm -f -- /node_modules
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends curl
rm -rf /var/lib/apt/lists/*
command -v curl >/dev/null
install -d -o appuser -g appuser "$HOME"
exec runuser -u appuser -- env \
HOME="$HOME" \
OPENCLAW_NO_ONBOARD="$OPENCLAW_NO_ONBOARD" \
OPENCLAW_NO_PROMPT="$OPENCLAW_NO_PROMPT" \
COREPACK_ENABLE_DOWNLOAD_PROMPT="$COREPACK_ENABLE_DOWNLOAD_PROMPT" \
OPENCLAW_SOURCE_SHA="$OPENCLAW_SOURCE_SHA" \
bash /tmp/source-proof.sh
' >/dev/null
docker_e2e_wait_for_proof "$HOSTED_PROOF_CONTAINER" 1200
docker logs "$HOSTED_PROOF_CONTAINER"
docker_e2e_wait_for_proof "$SOURCE_PROOF_CONTAINER" 1200
docker logs "$SOURCE_PROOF_CONTAINER"
echo "CLI installer distribution proof passed."