fix(update): preserve pnpm and Bun global installs (#107802)

* fix(update): preserve pnpm and bun global installs

* fix(update): anchor pnpm updates to invoking install

* fix(update): recover skipped pnpm lifecycle

* fix(update): fail closed on ambiguous pnpm ownership

* fix(update): tolerate pnpm probe warnings

* fix(update): bind pnpm installs to project owners

* fix(update): isolate pnpm mutations from caller pins

* docs(changelog): credit pnpm 11 report

Co-authored-by: jincheng-xydt <xu.jincheng@xydigit.com>

* chore(changelog): defer release note ownership

* fix(update): make package-root fallback explicit

* test(update): split pnpm scenario coverage

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
jincheng-xydt
2026-07-15 23:03:35 +08:00
committed by GitHub
parent c41f46260c
commit b2e42e3645
12 changed files with 2055 additions and 89 deletions
+28 -9
View File
@@ -1,14 +1,12 @@
#!/usr/bin/env bash
# Reproduces the multi-node-install update bug.
# Guards the multi-node-install update fix.
#
# Sets up two independent Node installations inside a Docker container, installs
# OpenClaw under node-A, registers the gateway service pointing at node-A, then
# switches PATH so node-B comes first and runs `openclaw update`. Verifies that:
#
# 1. The update targets the wrong install root (node-B npm prefix) or produces
# a gateway service definition pointing at node-B while the package lives
# under node-A.
# 2. The gateway fails to start or runs a stale/missing entrypoint.
# 1. The update stays on node-A's package root and service runtime.
# 2. The gateway restarts from the preserved entrypoint and becomes healthy.
#
# Usage:
# ./scripts/e2e/multi-node-update-docker.sh
@@ -206,7 +204,7 @@ start_gateway() {
echo "systemctl shim: unit not found: \$unit" >&2
return 1
fi
exec_start="\$(sed -n 's/^ExecStart=//p' "\$unit" | tail -n 1)"
exec_start="\$(sed -n "s/^ExecStart=//p" "\$unit" | tail -n 1)"
if [ -z "\$exec_start" ]; then
echo "systemctl shim: no ExecStart in \$unit" >&2
return 1
@@ -216,7 +214,7 @@ start_gateway() {
export OPENCLAW_NO_RESPAWN=1
echo "systemctl shim: starting: \$exec_start"
nohup bash -lc "exec \$exec_start" >>"$GATEWAY_DAEMON_LOG" 2>&1 &
printf '%s\n' "\$!" >"$GATEWAY_PID_FILE"
printf "%s\n" "\$!" >"$GATEWAY_PID_FILE"
)
}
@@ -247,9 +245,9 @@ case "\$command" in
;;
show)
if is_running; then
printf 'ActiveState=active\nSubState=running\nMainPID=%s\nExecMainStatus=0\nExecMainCode=0\n' "\$(cat "$GATEWAY_PID_FILE")"
printf "ActiveState=active\nSubState=running\nMainPID=%s\nExecMainStatus=0\nExecMainCode=0\n" "\$(cat "$GATEWAY_PID_FILE")"
else
printf 'ActiveState=inactive\nSubState=dead\nMainPID=0\nExecMainStatus=0\nExecMainCode=0\n'
printf "ActiveState=inactive\nSubState=dead\nMainPID=0\nExecMainStatus=0\nExecMainCode=0\n"
fi
;;
*)
@@ -271,6 +269,27 @@ if ! openclaw gateway install --json >"$ARTIFACTS/gateway-install.json" 2>"$ARTI
exit 1
fi
if ! openclaw gateway status --json \
>"$ARTIFACTS/gateway-status-before-update.json" \
2>"$ARTIFACTS/gateway-status-before-update.err"; then
echo "FAIL: gateway status failed before update"
cat "$ARTIFACTS/gateway-status-before-update.err" 2>/dev/null || true
exit 1
fi
if ! GATEWAY_STATUS_FILE="$ARTIFACTS/gateway-status-before-update.json" node --input-type=module <<"NODE"
import fs from "node:fs";
const status = JSON.parse(fs.readFileSync(process.env.GATEWAY_STATUS_FILE, "utf8"));
if (status.service?.runtime?.status !== "running") {
console.error(`expected running gateway service before update, got \${status.service?.runtime?.status ?? "missing"}`);
process.exit(1);
}
NODE
then
echo "FAIL: gateway service was not running before update"
cat "$ARTIFACTS/gateway-status-before-update.json" 2>/dev/null || true
exit 1
fi
echo ""
echo "── Step 4: Inspect what node path was baked into the service ──"