Files
openclaw/scripts/e2e/update-run-package-self-upgrade-docker.sh
Vincent Koc b4faa5aa5e chore(gateway): cover update and setup RPCs
* test(gateway): cover update and setup RPCs

* test(gateway): cover target wizard lifecycle

* test(gateway): normalize QA fixture ownership

* test(gateway): include historical dist closure

* test(gateway): isolate historical update fixture

* test(qa): align target wizard lifecycle proof

* test(qa): read structured gateway call errors
2026-08-04 09:15:55 +08:00

174 lines
6.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Proves a published package can update itself through Gateway update.run and restart healthy.
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
source "$ROOT_DIR/scripts/lib/docker-e2e-package.sh"
ALLOW_ENV="OPENCLAW_QA_ALLOW_UPDATE_RUN_SELF"
SOURCE_VERSION="2026.4.26"
SOURCE_TAG="v$SOURCE_VERSION"
SOURCE_COMMIT="be8c24633aaa7ef0425ae1178f096ee8dd6226c0"
if [ "${OPENCLAW_QA_ALLOW_UPDATE_RUN_SELF:-0}" != "1" ]; then
echo "blocked destructive package self-upgrade; set $ALLOW_ENV=1 to run" >&2
exit 2
fi
IMAGE_NAME="$(
docker_e2e_resolve_image \
"openclaw-update-run-package-self-upgrade-e2e" \
OPENCLAW_UPDATE_RUN_SELF_UPGRADE_E2E_IMAGE
)"
SKIP_BUILD="${OPENCLAW_UPDATE_RUN_SELF_UPGRADE_E2E_SKIP_BUILD:-0}"
DOCKER_RUN_TIMEOUT="${OPENCLAW_UPDATE_RUN_SELF_UPGRADE_DOCKER_RUN_TIMEOUT:-1800s}"
ARTIFACT_DIR="${OPENCLAW_UPDATE_RUN_SELF_UPGRADE_ARTIFACT_DIR:-$ROOT_DIR/.artifacts/update-run-package-self-upgrade}"
QA_CHANNEL_FIXTURE_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/openclaw-update-run-qa-channel.XXXXXX")"
HISTORICAL_DIST_ARCHIVE="$QA_CHANNEL_FIXTURE_ROOT/historical-dist.tar"
cleanup() {
rm -rf "$QA_CHANNEL_FIXTURE_ROOT"
}
trap cleanup EXIT
prepare_qa_channel_fixture() {
local source_repo="$ROOT_DIR"
local source_ref="$SOURCE_COMMIT"
local clone_root=""
local resolved_commit=""
local tag_commit=""
local tag_object=""
if ! git -C "$source_repo" cat-file -e "$SOURCE_COMMIT^{commit}" 2>/dev/null || \
! git -C "$source_repo" cat-file -e "$SOURCE_TAG^{commit}" 2>/dev/null; then
clone_root="$QA_CHANNEL_FIXTURE_ROOT/source"
git clone \
--depth=1 \
--filter=blob:none \
--single-branch \
--branch "$SOURCE_TAG" \
https://github.com/openclaw/openclaw.git \
"$clone_root"
source_repo="$clone_root"
source_ref="HEAD"
fi
resolved_commit="$(git -C "$source_repo" rev-parse "$source_ref^{commit}")"
tag_commit="$(git -C "$source_repo" rev-parse "$SOURCE_TAG^{commit}")"
tag_object="$(git -C "$source_repo" rev-parse "$SOURCE_TAG")"
if [ "$resolved_commit" != "$SOURCE_COMMIT" ] || [ "$tag_commit" != "$SOURCE_COMMIT" ]; then
echo "$SOURCE_TAG/source fixture resolved to unexpected commits: tag=$tag_commit source=$resolved_commit" >&2
return 1
fi
SOURCE_TAG="$SOURCE_TAG" \
SOURCE_COMMIT="$SOURCE_COMMIT" \
TAG_OBJECT="$tag_object" \
node -e '
const fs = require("node:fs");
fs.writeFileSync(
process.argv[1],
`${JSON.stringify({
tag: process.env.SOURCE_TAG,
tagObject: process.env.TAG_OBJECT,
commit: process.env.SOURCE_COMMIT,
buildCommand: "OPENCLAW_BUILD_PRIVATE_QA=1 corepack pnpm build:docker",
runtimeInstall: `npm install --prefix <isolated-root> --omit=dev openclaw@${process.env.SOURCE_TAG.slice(1)}`,
privateDistOverlay: true,
}, null, 2)}\n`,
);
' "$ARTIFACT_DIR/qa-channel-fixture-provenance.json"
local checkout_root="$QA_CHANNEL_FIXTURE_ROOT/checkout"
mkdir -p "$checkout_root"
git -C "$source_repo" archive "$source_ref" | tar -x -C "$checkout_root"
local package_json="$checkout_root/extensions/qa-channel/package.json"
local fixture_version
fixture_version="$(node -p 'JSON.parse(require("node:fs").readFileSync(process.argv[1], "utf8")).version' "$package_json")"
if [ "$fixture_version" != "2026.4.25" ]; then
echo "historical QA channel fixture version mismatch: expected 2026.4.25, got $fixture_version" >&2
return 1
fi
echo "Building the tagged QA channel with the shipped Docker build" | tee "$ARTIFACT_DIR/historical-qa-channel-build.log"
(
cd "$checkout_root"
COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack pnpm install --frozen-lockfile
COREPACK_ENABLE_DOWNLOAD_PROMPT=0 OPENCLAW_BUILD_PRIVATE_QA=1 corepack pnpm build:docker
) >>"$ARTIFACT_DIR/historical-qa-channel-build.log" 2>&1
local compiled_plugin="$checkout_root/dist/extensions/qa-channel"
for required_file in package.json openclaw.plugin.json index.js setup-entry.js; do
if [ ! -f "$compiled_plugin/$required_file" ]; then
echo "shipped build omitted QA channel artifact $required_file" >&2
return 1
fi
done
tar -C "$checkout_root" -cf "$HISTORICAL_DIST_ARCHIVE" dist
}
mkdir -p "$ARTIFACT_DIR"
chmod -R a+rwX "$ARTIFACT_DIR" || true
prepare_qa_channel_fixture
docker_e2e_build_or_reuse \
"$IMAGE_NAME" \
update-run-package-self-upgrade \
"$ROOT_DIR/scripts/e2e/Dockerfile" \
"$ROOT_DIR" \
bare \
"$SKIP_BUILD"
echo "Running Gateway update.run package self-upgrade Docker E2E..."
docker_e2e_run_with_harness \
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
-e OPENCLAW_QA_ALLOW_UPDATE_RUN_SELF=1 \
-e OPENCLAW_UPDATE_RUN_SELF_UPGRADE_ARTIFACT_DIR=/tmp/openclaw-update-run-artifacts \
-e OPENCLAW_UPDATE_RUN_SELF_UPGRADE_SOURCE_VERSION="$SOURCE_VERSION" \
-v "$ARTIFACT_DIR:/tmp/openclaw-update-run-artifacts" \
-v "$HISTORICAL_DIST_ARCHIVE:/tmp/openclaw-update-run-historical-dist.tar:ro" \
"$IMAGE_NAME" \
timeout --kill-after=30s "$DOCKER_RUN_TIMEOUT" \
bash -lc 'set -euo pipefail
historical_install_root=/tmp/openclaw-update-run-historical-install
historical_package_root="$historical_install_root/node_modules/openclaw"
qa_plugin_link=/tmp/openclaw-update-run-build/dist/extensions/qa-channel
npm install \
--prefix "$historical_install_root" \
--omit=dev \
--no-fund \
--no-audit \
"openclaw@$OPENCLAW_UPDATE_RUN_SELF_UPGRADE_SOURCE_VERSION" \
2>&1 | tee /tmp/openclaw-update-run-artifacts/historical-package-install.log
tar --no-same-owner \
-xf /tmp/openclaw-update-run-historical-dist.tar \
-C "$historical_package_root"
mkdir -p "$(dirname "$qa_plugin_link")"
ln -s "$historical_package_root/dist/extensions/qa-channel" "$qa_plugin_link"
HISTORICAL_PACKAGE_ROOT="$historical_package_root" \
HISTORICAL_PLUGIN_ENTRY="$historical_package_root/dist/extensions/qa-channel/index.js" \
HISTORICAL_PREFLIGHT_OUT=/tmp/openclaw-update-run-artifacts/historical-package-preflight.json \
node --input-type=module <<NODE
import fs from "node:fs";
import path from "node:path";
import { pathToFileURL } from "node:url";
const packageRoot = process.env.HISTORICAL_PACKAGE_ROOT;
const pluginEntry = process.env.HISTORICAL_PLUGIN_ENTRY;
const packageVersion = JSON.parse(
fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"),
).version;
const pluginVersion = JSON.parse(
fs.readFileSync(path.join(path.dirname(pluginEntry), "package.json"), "utf8"),
).version;
if (packageVersion !== process.env.OPENCLAW_UPDATE_RUN_SELF_UPGRADE_SOURCE_VERSION) {
throw new Error("isolated historical package version mismatch: " + packageVersion);
}
await import(pathToFileURL(pluginEntry).href);
fs.writeFileSync(
process.env.HISTORICAL_PREFLIGHT_OUT,
JSON.stringify({ packageVersion, pluginVersion, pluginEntryImported: true }, null, 2) + "\n",
);
NODE
exec bash scripts/e2e/lib/upgrade-survivor/update-run-package-self-upgrade.sh'