Files
openclaw/scripts/e2e/plugin-update-unchanged-docker.sh
2026-04-26 23:10:33 +01:00

170 lines
5.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Verifies `openclaw plugins update` is a no-op for an already-current plugin.
# The CLI under test is installed from the prepared npm tarball in a bare runner.
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"
IMAGE_NAME="$(docker_e2e_resolve_image "openclaw-plugin-update-e2e" OPENCLAW_PLUGIN_UPDATE_E2E_IMAGE)"
SKIP_BUILD="${OPENCLAW_PLUGIN_UPDATE_E2E_SKIP_BUILD:-0}"
PACKAGE_TGZ="$(docker_e2e_prepare_package_tgz plugin-update "${OPENCLAW_CURRENT_PACKAGE_TGZ:-}")"
# Bare lanes mount the package artifact instead of baking app sources into the image.
docker_e2e_package_mount_args "$PACKAGE_TGZ"
docker_e2e_build_or_reuse "$IMAGE_NAME" plugin-update "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR" "bare" "$SKIP_BUILD"
echo "Running unchanged plugin update smoke..."
docker run --rm \
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
-e OPENCLAW_SKIP_CHANNELS=1 \
-e OPENCLAW_SKIP_PROVIDERS=1 \
"${DOCKER_E2E_PACKAGE_ARGS[@]}" \
"$IMAGE_NAME" \
bash -lc "set -euo pipefail
package_tgz=\"\${OPENCLAW_CURRENT_PACKAGE_TGZ:?missing OPENCLAW_CURRENT_PACKAGE_TGZ}\"
npm install -g --prefix /tmp/npm-prefix \"\$package_tgz\" --no-fund --no-audit >/tmp/openclaw-install.log 2>&1
entry=\"/tmp/npm-prefix/lib/node_modules/openclaw/dist/index.mjs\"
[ -f \"\$entry\" ] || entry=/tmp/npm-prefix/lib/node_modules/openclaw/dist/index.js
export NPM_CONFIG_REGISTRY=http://127.0.0.1:4873
export PATH=\"/tmp/npm-prefix/bin:\$PATH\"
mkdir -p \"\$HOME/.openclaw/extensions/lossless-claw\"
cat > \"\$HOME/.openclaw/extensions/lossless-claw/package.json\" <<'JSON'
{
\"name\": \"@example/lossless-claw\",
\"version\": \"0.9.0\"
}
JSON
cat > \"\$HOME/.openclaw/openclaw.json\" <<'JSON'
{
\"plugins\": {}
}
JSON
mkdir -p \"\$HOME/.openclaw/plugins\"
cat > \"\$HOME/.openclaw/plugins/installs.json\" <<'JSON'
{
\"version\": 1,
\"warning\": \"DO NOT EDIT. This file is generated by OpenClaw plugin registry commands.\",
\"hostContractVersion\": \"docker-e2e\",
\"compatRegistryVersion\": \"docker-e2e\",
\"migrationVersion\": 1,
\"policyHash\": \"docker-e2e\",
\"generatedAtMs\": 1777118400000,
\"installRecords\": {
\"lossless-claw\": {
\"source\": \"npm\",
\"spec\": \"@example/lossless-claw@0.9.0\",
\"installPath\": \"~/.openclaw/extensions/lossless-claw\",
\"resolvedName\": \"@example/lossless-claw\",
\"resolvedVersion\": \"0.9.0\",
\"resolvedSpec\": \"@example/lossless-claw@0.9.0\",
\"integrity\": \"sha512-same\",
\"shasum\": \"same\"
}
},
\"plugins\": [],
\"diagnostics\": []
}
JSON
cat > /tmp/openclaw-e2e-registry.mjs <<'NODE'
import http from 'node:http';
const metadata = {
name: '@example/lossless-claw',
'dist-tags': { latest: '0.9.0' },
versions: {
'0.9.0': {
name: '@example/lossless-claw',
version: '0.9.0',
dist: {
integrity: 'sha512-same',
shasum: 'same',
tarball: 'http://127.0.0.1:4873/@example/lossless-claw/-/lossless-claw-0.9.0.tgz'
}
}
}
};
const server = http.createServer((req, res) => {
if (req.url === '/@example%2flossless-claw' || req.url === '/@example%2Flossless-claw') {
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify(metadata));
return;
}
res.writeHead(404, { 'content-type': 'text/plain' });
res.end('not found: ' + req.url);
});
server.listen(4873, '127.0.0.1');
NODE
node /tmp/openclaw-e2e-registry.mjs >/tmp/openclaw-e2e-registry.log 2>&1 &
registry_pid=\$!
trap 'kill \"\$registry_pid\" >/dev/null 2>&1 || true' EXIT
registry_ready=0
for _ in \$(seq 1 50); do
if node --input-type=module -e '
import http from \"node:http\";
const req = http.get(\"http://127.0.0.1:4873/@example%2flossless-claw\", (res) => {
process.exit(res.statusCode === 200 ? 0 : 1);
});
req.on(\"error\", () => process.exit(1));
req.setTimeout(200, () => {
req.destroy();
process.exit(1);
});
'; then
registry_ready=1
break
fi
sleep 0.1
done
if [ \"\$registry_ready\" -ne 1 ]; then
echo \"Local npm metadata registry failed to start\"
cat /tmp/openclaw-e2e-registry.log || true
exit 1
fi
before_hash=\$(node --input-type=module -e '
import crypto from \"node:crypto\";
import fs from \"node:fs\";
import os from \"node:os\";
import path from \"node:path\";
const file = path.join(os.homedir(), \".openclaw\", \"openclaw.json\");
process.stdout.write(crypto.createHash(\"sha256\").update(fs.readFileSync(file)).digest(\"hex\"));
')
node \"\$entry\" plugins update @example/lossless-claw > /tmp/plugin-update-output.log 2>&1
after_hash=\$(node --input-type=module -e '
import crypto from \"node:crypto\";
import fs from \"node:fs\";
import os from \"node:os\";
import path from \"node:path\";
const file = path.join(os.homedir(), \".openclaw\", \"openclaw.json\");
process.stdout.write(crypto.createHash(\"sha256\").update(fs.readFileSync(file)).digest(\"hex\"));
')
if [ \"\$before_hash\" != \"\$after_hash\" ]; then
echo \"Config changed unexpectedly\"
cat /tmp/plugin-update-output.log
exit 1
fi
if grep -q 'Downloading @example/lossless-claw' /tmp/plugin-update-output.log; then
echo \"Unexpected npm download/reinstall path\"
cat /tmp/plugin-update-output.log
exit 1
fi
if ! grep -q 'lossless-claw is up to date (0.9.0).' /tmp/plugin-update-output.log; then
echo \"Expected up-to-date output missing\"
cat /tmp/plugin-update-output.log
exit 1
fi
cat /tmp/plugin-update-output.log
"
echo "Plugin update unchanged Docker E2E passed."