mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 17:53:39 +00:00
Refresh application, plugin, native, build and container dependencies through the fixed 2026-09-19T16:27:11Z cutoff. Migrate native TypeScript snapshot/printer APIs while preserving compilation and filesystem contracts; retain existing patches and compatibility holds. Document offline container-image preparation. Include the verified compiler process-census and loading-clock fixture repairs and deterministic warm-history regression. Adopt the canonical production history fixes from #159924 and #159955. Land under the maintainer's explicit approval to treat proven pre-existing CI failures as non-blocking and repair main afterward. CI36365552098 failed an unchanged Android Compose fixture's asynchronous catalog projection assertion (3518 passed,1 failed); the Android/Gradle tree matches its main parent byte-for-byte. Security and dependency reviews passed. The final rebase preserves reviewed source changes and regenerates only the intentional Node-image documentation fingerprint. See PR159401 for complete validation and the follow-up repair obligation.
241 lines
9.1 KiB
Bash
Executable file
241 lines
9.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
node_version="24.21.0"
|
|
pnpm_spec="pnpm@12.5.1+sha512.e3f305bc784a2bc89f5ad3b6138889470fae8d2af5f36b61216ec91c2c3d64089775f9de38aac331044ea40f245cb0d5666392dfdf65824e1907ef6a2c62de5f"
|
|
# Keep exact formerly trusted pins so older contributor heads remain verifiable.
|
|
historical_pnpm_specs=(
|
|
"pnpm@12.5.0+sha512.9cdbaa34ffacae1768635ac0d23e94db6201c7d59bf3da236b23d67c8f6b794d1dab323bcd5bcc51b55c8cafbf6f19a24e4aa61d6ab7772aa3b5cc85e325dc4d"
|
|
"pnpm@12.4.2+sha512.08adc6613180275c7c9edada39dcf08c9c61ad4e7eaf330a4f3461f102b0f907423454d117f98e72d47fef0616070644d7bffc973a6a57f5090a6d7c368b07c9"
|
|
"pnpm@12.4.0+sha512.37536c26ed40ab4134b6511e09f6b27f3ebb45687468f2406ca3805279a4e5ca158c1931350ad9774d6ab2108d71b3dbaeb39943159294375e4d053e8e05685c"
|
|
"pnpm@12.3.4+sha512.961aa41fb077da3a04a441d9f8e15ebc0c96da8ef710b2eb67bf9ee7cb0610eabd48f1fd85f51cffe73846785fa0f87c56a3a872a1d893f8446741b5cce45457"
|
|
"pnpm@12.1.0+sha512.d9b8276d97f6ec86e49815877f91ee9f63cee61f2063b304e43b6dab8fa07ce8a9afd46d2facd39f921e6a9d06b3c75a81349c7b888c2d22886bae0229901037"
|
|
)
|
|
|
|
if [[ $# -lt 2 ]]; then
|
|
echo "usage: $0 <expected-head-sha> <command> [args...]" >&2
|
|
exit 2
|
|
fi
|
|
expected_head_sha="$1"
|
|
shift
|
|
unset NODE_OPTIONS NODE_PATH COREPACK_NPM_REGISTRY COREPACK_INTEGRITY_KEYS COREPACK_ENV_FILE
|
|
export COREPACK_ENV_FILE=0
|
|
|
|
imds_token="$(
|
|
/usr/bin/curl -fsS --connect-timeout 2 --max-time 5 -X PUT \
|
|
-H "X-aws-ec2-metadata-token-ttl-seconds: 60" \
|
|
http://169.254.169.254/latest/api/token
|
|
)"
|
|
iam_status="$(
|
|
/usr/bin/curl -sS --connect-timeout 2 --max-time 5 -o /dev/null -w "%{http_code}" \
|
|
-H "X-aws-ec2-metadata-token: ${imds_token}" \
|
|
http://169.254.169.254/latest/meta-data/iam/security-credentials/
|
|
)"
|
|
if [[ "$iam_status" != "404" ]]; then
|
|
echo "refusing untrusted bootstrap: IAM credentials endpoint returned ${iam_status}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
actual_head_sha="$(/usr/bin/git rev-parse HEAD)"
|
|
if [[ "$actual_head_sha" != "$expected_head_sha" ]]; then
|
|
echo "refusing untrusted run: expected HEAD ${expected_head_sha}, got ${actual_head_sha}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
case "$(/usr/bin/uname -m)" in
|
|
x86_64)
|
|
node_arch="x64"
|
|
node_sha256="fd8e59d5a511510f6a298afb548f18c7d2b1be404d8b4a27d94fbe49f56cb2d6"
|
|
;;
|
|
aarch64 | arm64)
|
|
node_arch="arm64"
|
|
node_sha256="6ad1325edbdb5649c379b75a237147a666c95d4f9ae8d340fef2d1575d289ad2"
|
|
;;
|
|
*)
|
|
echo "unsupported architecture: $(/usr/bin/uname -m)" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
archive="node-v${node_version}-linux-${node_arch}.tar.xz"
|
|
base_url="https://nodejs.org/dist/v${node_version}"
|
|
install_root="/opt/openclaw-untrusted-node-v${node_version}-${node_arch}"
|
|
corepack_home="/opt/openclaw-untrusted-corepack"
|
|
archive_root="/opt/crabbox/toolchain-archives"
|
|
tmp_dir="$(/usr/bin/mktemp -d)"
|
|
run_home=""
|
|
# Invoked by the EXIT trap.
|
|
# shellcheck disable=SC2329
|
|
cleanup() {
|
|
/bin/rm -rf -- "$tmp_dir"
|
|
if [[ -n "$run_home" ]]; then
|
|
/bin/rm -rf -- "$run_home"
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
verify_archive() {
|
|
local name="$1" checksum="$2" algorithm="$3"
|
|
printf '%s %s\n' "$checksum" "$tmp_dir/$name" | "/usr/bin/sha${algorithm}sum" --check --status
|
|
}
|
|
|
|
copy_verified_archive() {
|
|
local name="$1" checksum="$2" algorithm="$3"
|
|
# Never verify a shared path and then extract it: authenticate the private copy.
|
|
[[ -f "$archive_root/$name" ]] &&
|
|
/bin/cp -- "$archive_root/$name" "$tmp_dir/$name" &&
|
|
verify_archive "$name" "$checksum" "$algorithm"
|
|
}
|
|
|
|
if ! copy_verified_archive "$archive" "$node_sha256" 256; then
|
|
/usr/bin/curl -fsSL --connect-timeout 10 --max-time 300 --retry 2 \
|
|
-o "$tmp_dir/$archive" "$base_url/$archive"
|
|
if ! verify_archive "$archive" "$node_sha256" 256; then
|
|
echo "refusing untrusted bootstrap: downloaded $archive differs from the trusted digest" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
sudo /usr/bin/env -i PATH=/usr/bin:/bin /bin/bash -s -- \
|
|
"$install_root" "$tmp_dir/$archive" <<'INSTALL_NODE'
|
|
set -euo pipefail
|
|
umask 022
|
|
install_root="$1"
|
|
archive_path="$2"
|
|
/bin/rm -rf -- "$install_root"
|
|
/usr/bin/mkdir -p "$install_root"
|
|
/usr/bin/tar -xJf "$archive_path" -C "$install_root" --strip-components=1
|
|
INSTALL_NODE
|
|
|
|
candidate_package_json="$PWD/package.json"
|
|
pnpm_spec="$(
|
|
cd "$install_root"
|
|
"$install_root/bin/node" - "$candidate_package_json" "$pnpm_spec" "${historical_pnpm_specs[@]}" <<'PACKAGE_MANAGER'
|
|
const fs = require("node:fs");
|
|
const [file, ...approvedPins] = process.argv.slice(2);
|
|
let pkg;
|
|
try {
|
|
pkg = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
} catch {
|
|
console.error("refusing untrusted run: invalid package.json");
|
|
process.exit(1);
|
|
}
|
|
if (!approvedPins.includes(pkg?.packageManager)) {
|
|
console.error("refusing untrusted run: packageManager pin differs from trusted main or approved history");
|
|
process.exit(1);
|
|
}
|
|
process.stdout.write(pkg.packageManager);
|
|
PACKAGE_MANAGER
|
|
)"
|
|
|
|
pnpm_version="${pnpm_spec#pnpm@}"
|
|
pnpm_version="${pnpm_version%%+*}"
|
|
pnpm_native_sha512=""
|
|
case "$pnpm_version:$node_arch" in
|
|
12.5.1:x64)
|
|
pnpm_native_sha512="dcf914058a39cf8760b659d3348163ed01a9703500baa5f3f561958a03c309e71c127846891916980e75d364e66091edc093f72df984f9917d3c6796867f29f5"
|
|
;;
|
|
12.5.1:arm64)
|
|
pnpm_native_sha512="ea16cc596dbf790a356f9c2f40f7bf9dd2c75531fcf116afe8df9f7c3e3f87a22e14c8d60a06ac15862c16fd06aefa6a444031dd2c26652be58bed0d157a9bc4"
|
|
;;
|
|
12.5.0:x64)
|
|
pnpm_native_sha512="f27d1f5ed98258cab9e7c003d59796f5d2261bc4f0418eb0b3a8ec61ca1157edae04170b10727995f797bc18fdf749e87f04bb5d98a1a990efcb52c192729605"
|
|
;;
|
|
12.5.0:arm64)
|
|
pnpm_native_sha512="9f3b25522cbb2c01647b79e22ca752687714745788852288d35d35bb740a5aee90e13ffbe605304d4c5c30f573dacbd452672d5c0740bfa727a64c9fbcad92ae"
|
|
;;
|
|
12.4.2:x64)
|
|
pnpm_native_sha512="fe96edd145536bc34c0e1cce58b4117d9e86f5138a5e524f66dc7ce3906ac967dcee10ab5978532c177bd323b6cbcf84f8858dde81ccd6cfc9b0840d1a4d72be"
|
|
;;
|
|
12.4.2:arm64)
|
|
pnpm_native_sha512="d9d4a20d7ca1c7e4531ec7b0c5ec7c7ff8d58ea417589da8a30e240951c459d64a781a60331bd9e9f1e44c050125782a85b2880c7bee3656413fb8097d458be4"
|
|
;;
|
|
esac
|
|
pnpm_archive="pnpm-${pnpm_version}.tgz"
|
|
pnpm_native_archive="exe.linux-${node_arch}-${pnpm_version}.tgz"
|
|
pnpm_seed=""
|
|
if [[ -n "$pnpm_native_sha512" ]] &&
|
|
copy_verified_archive "$pnpm_archive" "${pnpm_spec##*+sha512.}" 512 &&
|
|
copy_verified_archive "$pnpm_native_archive" "$pnpm_native_sha512" 512; then
|
|
pnpm_seed="$tmp_dir"
|
|
fi
|
|
|
|
# Only public toolchain artifacts need shared access; keep caller state private.
|
|
sudo /usr/bin/env -i PATH=/usr/bin:/bin /bin/bash -s -- \
|
|
"$install_root" "$corepack_home" "$pnpm_spec" "$pnpm_seed" "$node_arch" <<'INSTALL'
|
|
set -euo pipefail
|
|
umask 022
|
|
install_root="$1"
|
|
corepack_home="$2"
|
|
pnpm_spec="$3"
|
|
pnpm_seed="$4"
|
|
node_arch="$5"
|
|
/bin/rm -rf -- "$corepack_home"
|
|
/usr/bin/mkdir -p "$corepack_home"
|
|
if [[ -n "$pnpm_seed" ]]; then
|
|
pnpm_version="${pnpm_spec#pnpm@}"
|
|
pnpm_version="${pnpm_version%%+*}"
|
|
pnpm_root="$corepack_home/v1/pnpm/$pnpm_version"
|
|
/usr/bin/mkdir -p "$pnpm_root"
|
|
/usr/bin/tar -xzf "$pnpm_seed/pnpm-${pnpm_version}.tgz" -C "$pnpm_root" --strip-components=1
|
|
native_root="$pnpm_root/node_modules/@pnpm/exe.linux-${node_arch}"
|
|
/usr/bin/mkdir -p "$native_root"
|
|
/usr/bin/tar -xzf "$pnpm_seed/exe.linux-${node_arch}-${pnpm_version}.tgz" \
|
|
-C "$native_root" --strip-components=1
|
|
# Corepack 0.35's v1 cache format, generated only from authenticated archives.
|
|
"$install_root/bin/node" - "$pnpm_root/.corepack" "$pnpm_spec" <<'METADATA'
|
|
const fs = require("node:fs");
|
|
const [file, spec] = process.argv.slice(2);
|
|
fs.writeFileSync(file, JSON.stringify({
|
|
locator: { name: "pnpm", reference: spec.slice("pnpm@".length) },
|
|
bin: { pnpm: "./bin/pnpm.mjs", pnpx: "./bin/pnpx.mjs" },
|
|
hash: spec.slice(spec.indexOf("+") + 1),
|
|
}));
|
|
METADATA
|
|
export COREPACK_ENABLE_NETWORK=0
|
|
fi
|
|
# Corepack must select and warm the approved pin outside the untrusted checkout.
|
|
cd "$install_root"
|
|
/usr/bin/env \
|
|
COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
|
|
COREPACK_HOME="$corepack_home" \
|
|
PATH="$install_root/bin:/usr/bin:/bin" \
|
|
"$install_root/bin/corepack" enable --install-directory "$install_root/bin"
|
|
/usr/bin/env \
|
|
COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
|
|
COREPACK_HOME="$corepack_home" \
|
|
PATH="$install_root/bin:/usr/bin:/bin" \
|
|
"$install_root/bin/corepack" prepare "$pnpm_spec" --activate
|
|
/usr/bin/env \
|
|
COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
|
|
COREPACK_HOME="$corepack_home" \
|
|
PATH="$install_root/bin:/usr/bin:/bin" \
|
|
"$install_root/bin/corepack" "$pnpm_spec" --version
|
|
INSTALL
|
|
|
|
for tool in node npm npx corepack pnpm pnpx; do
|
|
if [[ -e "$install_root/bin/$tool" ]]; then
|
|
sudo /usr/bin/ln -sfn "$install_root/bin/$tool" "/usr/local/bin/$tool"
|
|
fi
|
|
done
|
|
|
|
/usr/local/bin/node --version
|
|
|
|
actual_package_manager="$(
|
|
/usr/local/bin/node -e \
|
|
'const fs = require("node:fs"); const pkg = JSON.parse(fs.readFileSync("package.json", "utf8")); process.stdout.write(pkg.packageManager || "")'
|
|
)"
|
|
if [[ "$actual_package_manager" != "$pnpm_spec" ]]; then
|
|
echo "refusing untrusted run: packageManager pin changed during bootstrap" >&2
|
|
exit 1
|
|
fi
|
|
|
|
run_home="$(/usr/bin/mktemp -d)"
|
|
export HOME="$run_home"
|
|
export COREPACK_HOME="$corepack_home"
|
|
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
|
/usr/local/bin/pnpm --version
|
|
/usr/local/bin/pnpm install --frozen-lockfile
|
|
command_status=0
|
|
"$@" || command_status=$?
|
|
exit "$command_status"
|