mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
fix: improve macos parallels npm smoke installs
This commit is contained in:
63
scripts/e2e/lib/parallels-macos-common.sh
Normal file
63
scripts/e2e/lib/parallels-macos-common.sh
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
parallels_macos_resolve_desktop_user() {
|
||||
local vm_name="$1"
|
||||
local user
|
||||
user="$(prlctl exec "$vm_name" /usr/bin/stat -f '%Su' /dev/console 2>/dev/null | tr -d '\r' | tail -n 1 || true)"
|
||||
if [[ "$user" =~ ^[A-Za-z0-9._-]+$ && "$user" != "root" && "$user" != "loginwindow" ]]; then
|
||||
printf '%s\n' "$user"
|
||||
return 0
|
||||
fi
|
||||
prlctl exec "$vm_name" /usr/bin/dscl . -list /Users NFSHomeDirectory 2>/dev/null \
|
||||
| tr -d '\r' \
|
||||
| awk '$2 ~ /^\/Users\// && $1 !~ /^_/ && $1 != "Shared" && $1 != ".localized" { print $1; exit }'
|
||||
}
|
||||
|
||||
parallels_macos_resolve_desktop_home() {
|
||||
local vm_name="$1"
|
||||
local user="$2"
|
||||
local home
|
||||
home="$(
|
||||
prlctl exec "$vm_name" /usr/bin/dscl . -read "/Users/$user" NFSHomeDirectory 2>/dev/null \
|
||||
| tr -d '\r' \
|
||||
| awk '/NFSHomeDirectory:/ { print $2; exit }'
|
||||
)"
|
||||
if [[ -n "$home" ]]; then
|
||||
printf '%s\n' "$home"
|
||||
else
|
||||
printf '/Users/%s\n' "$user"
|
||||
fi
|
||||
}
|
||||
|
||||
parallels_macos_current_user_available() {
|
||||
local vm_name="$1"
|
||||
prlctl exec "$vm_name" --current-user /usr/bin/whoami >/dev/null 2>&1
|
||||
}
|
||||
|
||||
parallels_macos_desktop_user_exec() {
|
||||
local vm_name="$1"
|
||||
local api_key_env="$2"
|
||||
local api_key_value="$3"
|
||||
shift 3
|
||||
|
||||
if parallels_macos_current_user_available "$vm_name"; then
|
||||
prlctl exec "$vm_name" --current-user /usr/bin/env "$api_key_env=$api_key_value" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
local user home
|
||||
user="$(parallels_macos_resolve_desktop_user "$vm_name")"
|
||||
[[ -n "$user" ]] || {
|
||||
printf 'unable to resolve macOS desktop user for sudo fallback\n' >&2
|
||||
return 1
|
||||
}
|
||||
home="$(parallels_macos_resolve_desktop_home "$vm_name" "$user")"
|
||||
printf 'warn: macOS --current-user unavailable; using root sudo fallback for %s\n' "$user" >&2
|
||||
prlctl exec "$vm_name" /usr/bin/sudo -u "$user" /usr/bin/env \
|
||||
"HOME=$home" \
|
||||
"USER=$user" \
|
||||
"LOGNAME=$user" \
|
||||
"PATH=/opt/homebrew/bin:/opt/homebrew/opt/node/bin:/opt/homebrew/sbin:/usr/bin:/bin:/usr/sbin:/sbin" \
|
||||
"$api_key_env=$api_key_value" \
|
||||
"$@"
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/e2e/lib/parallels-macos-common.sh"
|
||||
|
||||
VM_NAME="macOS Tahoe"
|
||||
SNAPSHOT_HINT="macOS 26.3.1 latest"
|
||||
@@ -38,11 +39,14 @@ GUEST_CURRENT_USER_TRANSPORT="prlctl"
|
||||
MAIN_TGZ_DIR="$(mktemp -d)"
|
||||
MAIN_TGZ_PATH=""
|
||||
PACKED_MAIN_COMMIT_SHORT=""
|
||||
TARGET_EXPECT_VERSION=""
|
||||
SERVER_PID=""
|
||||
RUN_DIR="$(mktemp -d /tmp/openclaw-parallels-smoke.XXXXXX)"
|
||||
BUILD_LOCK_DIR="${TMPDIR:-/tmp}/openclaw-parallels-build.lock"
|
||||
|
||||
TIMEOUT_INSTALL_S=900
|
||||
TIMEOUT_INSTALL_SITE_S=900
|
||||
TIMEOUT_INSTALL_TGZ_S=900
|
||||
TIMEOUT_INSTALL_REGISTRY_S=480
|
||||
TIMEOUT_UPDATE_DEV_S=1500
|
||||
TIMEOUT_VERIFY_S=60
|
||||
TIMEOUT_ONBOARD_S=180
|
||||
@@ -71,6 +75,10 @@ say() {
|
||||
}
|
||||
|
||||
artifact_label() {
|
||||
if target_package_installs_directly; then
|
||||
printf 'target package spec'
|
||||
return
|
||||
fi
|
||||
if [[ -n "$TARGET_PACKAGE_SPEC" ]]; then
|
||||
printf 'target package tgz'
|
||||
return
|
||||
@@ -78,6 +86,16 @@ artifact_label() {
|
||||
printf 'current main tgz'
|
||||
}
|
||||
|
||||
target_package_installs_directly() {
|
||||
[[ -n "$TARGET_PACKAGE_SPEC" ]] || return 1
|
||||
case "$TARGET_PACKAGE_SPEC" in
|
||||
http://*|https://*|file:*|/*|./*|../*|*.tgz)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
warn() {
|
||||
printf 'warn: %s\n' "$*" >&2
|
||||
}
|
||||
@@ -116,9 +134,9 @@ Options:
|
||||
--snapshot-hint <name> Snapshot name substring/fuzzy match.
|
||||
Default: "macOS 26.3.1 latest"
|
||||
--mode <fresh|upgrade|both>
|
||||
fresh = fresh snapshot -> target package/current main tgz -> onboard smoke
|
||||
fresh = fresh snapshot -> target package/current main install artifact -> onboard smoke
|
||||
upgrade = fresh snapshot -> pinned latest stable -> dev channel update -> onboard smoke
|
||||
(or latest stable -> target package tgz when --target-package-spec is set)
|
||||
(or latest stable -> target package install when --target-package-spec is set)
|
||||
both = run both lanes
|
||||
--provider <openai|anthropic|minimax>
|
||||
Provider auth/model lane. Default: openai
|
||||
@@ -273,12 +291,25 @@ discord_smoke_enabled() {
|
||||
[[ -n "$DISCORD_TOKEN_VALUE" && -n "$DISCORD_GUILD_ID" && -n "$DISCORD_CHANNEL_ID" ]]
|
||||
}
|
||||
|
||||
fresh_uses_host_tgz() {
|
||||
if [[ -z "$TARGET_PACKAGE_SPEC" ]]; then
|
||||
return 0
|
||||
fi
|
||||
! target_package_installs_directly
|
||||
}
|
||||
|
||||
upgrade_uses_host_tgz() {
|
||||
[[ -n "$TARGET_PACKAGE_SPEC" ]]
|
||||
[[ -n "$TARGET_PACKAGE_SPEC" ]] && ! target_package_installs_directly
|
||||
}
|
||||
|
||||
needs_host_tgz() {
|
||||
[[ "$MODE" == "fresh" || "$MODE" == "both" ]] || upgrade_uses_host_tgz
|
||||
if [[ "$MODE" == "fresh" || "$MODE" == "both" ]]; then
|
||||
fresh_uses_host_tgz && return 0
|
||||
fi
|
||||
if [[ "$MODE" == "upgrade" || "$MODE" == "both" ]]; then
|
||||
upgrade_uses_host_tgz && return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
upgrade_summary_label() {
|
||||
@@ -484,8 +515,7 @@ wait_for_vm_status() {
|
||||
}
|
||||
|
||||
resolve_headless_guest_user() {
|
||||
prlctl exec "$VM_NAME" /usr/bin/dscl . -list /Users NFSHomeDirectory 2>/dev/null \
|
||||
| awk '$2 ~ /^\/Users\// && $1 !~ /^_/ && $1 != "Shared" && $1 != ".localized" { print $1; exit }'
|
||||
parallels_macos_resolve_desktop_user "$VM_NAME"
|
||||
}
|
||||
|
||||
guest_current_user_transport_path() {
|
||||
@@ -606,8 +636,10 @@ guest_current_user_exec_path() {
|
||||
local path_value="$1"
|
||||
shift
|
||||
if headless_guest_fallback; then
|
||||
local guest_home
|
||||
guest_home="$(parallels_macos_resolve_desktop_home "$VM_NAME" "$GUEST_CURRENT_USER")"
|
||||
prlctl exec "$VM_NAME" /usr/bin/sudo -H -u "$GUEST_CURRENT_USER" /usr/bin/env \
|
||||
"HOME=/Users/$GUEST_CURRENT_USER" \
|
||||
"HOME=$guest_home" \
|
||||
"USER=$GUEST_CURRENT_USER" \
|
||||
"LOGNAME=$GUEST_CURRENT_USER" \
|
||||
"PATH=$path_value" \
|
||||
@@ -630,7 +662,7 @@ guest_current_user_node_cli() {
|
||||
resolve_guest_current_user_home() {
|
||||
local user_name
|
||||
user_name="$(guest_current_user_exec /usr/bin/id -un | tr -d '\r')"
|
||||
printf '/Users/%s\n' "$user_name"
|
||||
parallels_macos_resolve_desktop_home "$VM_NAME" "$user_name"
|
||||
}
|
||||
|
||||
resolve_guest_git_openclaw_entry() {
|
||||
@@ -714,9 +746,11 @@ guest_current_user_sh() {
|
||||
script+="$1"
|
||||
if headless_guest_fallback; then
|
||||
script_path="/tmp/openclaw-prl-${BASHPID:-$$}-$RANDOM.sh"
|
||||
local guest_home
|
||||
guest_home="$(parallels_macos_resolve_desktop_home "$VM_NAME" "$GUEST_CURRENT_USER")"
|
||||
printf '%s' "$script" | /usr/bin/base64 | prlctl exec "$VM_NAME" \
|
||||
/usr/bin/sudo -H -u "$GUEST_CURRENT_USER" /usr/bin/env \
|
||||
"HOME=/Users/$GUEST_CURRENT_USER" \
|
||||
"HOME=$guest_home" \
|
||||
"USER=$GUEST_CURRENT_USER" \
|
||||
"LOGNAME=$GUEST_CURRENT_USER" \
|
||||
/usr/bin/base64 -D -o "$script_path"
|
||||
@@ -736,6 +770,83 @@ guest_current_user_tail_file() {
|
||||
guest_current_user_exec /usr/bin/tail -n "$lines" "$file_path"
|
||||
}
|
||||
|
||||
latest_guest_npm_debug_log_path() {
|
||||
local guest_home="$1"
|
||||
guest_current_user_sh "$(cat <<EOF
|
||||
/usr/bin/python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
|
||||
logs = Path($(shell_quote "$guest_home")) / ".npm" / "_logs"
|
||||
candidates = sorted(
|
||||
logs.glob("*-debug-0.log"),
|
||||
key=lambda path: path.stat().st_mtime,
|
||||
reverse=True,
|
||||
)
|
||||
if candidates:
|
||||
print(candidates[0])
|
||||
PY
|
||||
EOF
|
||||
)" | tr -d '\r' | tail -n 1
|
||||
}
|
||||
|
||||
guest_runner_rc_from_log() {
|
||||
local log_path="$1"
|
||||
guest_current_user_sh "$(cat <<EOF
|
||||
/usr/bin/python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
|
||||
path = Path($(shell_quote "$log_path"))
|
||||
if not path.exists():
|
||||
raise SystemExit(1)
|
||||
|
||||
markers = [
|
||||
line.strip()
|
||||
for line in path.read_text(encoding="utf-8", errors="replace").splitlines()
|
||||
if line.startswith("__OPENCLAW_RC__:")
|
||||
]
|
||||
if not markers:
|
||||
raise SystemExit(1)
|
||||
|
||||
print(markers[-1].split(":", 1)[1])
|
||||
PY
|
||||
EOF
|
||||
)" | tr -d '\r' | tail -n 1
|
||||
}
|
||||
|
||||
stream_guest_file_delta() {
|
||||
local remote_path="$1"
|
||||
local state_path="$2"
|
||||
local prefix="$3"
|
||||
local content rc
|
||||
[[ -n "$remote_path" ]] || return 0
|
||||
set +e
|
||||
content="$(guest_current_user_exec /bin/cat "$remote_path" 2>/dev/null)"
|
||||
rc=$?
|
||||
set -e
|
||||
[[ $rc -eq 0 ]] || return 0
|
||||
CONTENT="$content" PREFIX="$prefix" python3 - "$state_path" <<'PY'
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
state_path = pathlib.Path(sys.argv[1])
|
||||
previous = state_path.read_text(encoding="utf-8", errors="replace") if state_path.exists() else ""
|
||||
current = os.environ["CONTENT"].replace("\r\n", "\n").replace("\r", "\n")
|
||||
prefix = os.environ["PREFIX"]
|
||||
|
||||
if current.startswith(previous):
|
||||
delta = current[len(previous):]
|
||||
else:
|
||||
delta = current
|
||||
|
||||
if delta:
|
||||
for line in delta.splitlines():
|
||||
print(f"{prefix}{line}")
|
||||
|
||||
state_path.write_text(current, encoding="utf-8")
|
||||
PY
|
||||
}
|
||||
|
||||
run_logged_guest_current_user_sh() {
|
||||
local script="$1"
|
||||
local log_path="$2"
|
||||
@@ -743,23 +854,22 @@ run_logged_guest_current_user_sh() {
|
||||
local timeout_s="$4"
|
||||
local runner_path="$5"
|
||||
local deadline rc runner_body write_runner_cmd
|
||||
if headless_guest_fallback; then
|
||||
set +e
|
||||
guest_current_user_sh "$script" >"$log_path" 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
return "$rc"
|
||||
fi
|
||||
local guest_home guest_log_state_path latest_npm_log_path latest_npm_log_state_path npm_state_path
|
||||
guest_current_user_exec /bin/rm -f "$log_path" "$done_path" "$runner_path"
|
||||
runner_body="$(cat <<EOF
|
||||
set -eu
|
||||
set -o pipefail
|
||||
trap 'status=\$?; printf "%s\n" "\$status" > "$done_path"; exit "\$status"' EXIT
|
||||
umask 022
|
||||
export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node/bin:/opt/homebrew/sbin:/usr/bin:/bin:/usr/sbin:/sbin:\${PATH:-}"
|
||||
if [ -z "\${HOME:-}" ]; then export HOME="/Users/\$(id -un)"; fi
|
||||
cd "\$HOME"
|
||||
$script
|
||||
status=0
|
||||
(
|
||||
set -eu
|
||||
set -o pipefail
|
||||
umask 022
|
||||
export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node/bin:/opt/homebrew/sbin:/usr/bin:/bin:/usr/sbin:/sbin:\${PATH:-}"
|
||||
if [ -z "\${HOME:-}" ]; then export HOME="/Users/\$(id -un)"; fi
|
||||
cd "\$HOME"
|
||||
$script
|
||||
) || status=\$?
|
||||
printf '__OPENCLAW_RC__:%s\n' "\$status"
|
||||
printf '%s\n' "\$status" > "$done_path"
|
||||
exit "\$status"
|
||||
EOF
|
||||
)"
|
||||
write_runner_cmd="/bin/rm -f $(shell_quote "$runner_path")"$'\n'
|
||||
@@ -767,18 +877,41 @@ EOF
|
||||
write_runner_cmd+="$runner_body"$'\n'
|
||||
write_runner_cmd+="__OPENCLAW_RUNNER__"$'\n'
|
||||
write_runner_cmd+="/bin/chmod +x $(shell_quote "$runner_path")"$'\n'
|
||||
write_runner_cmd+="nohup /bin/bash $(shell_quote "$runner_path") > $(shell_quote "$log_path") 2>&1 < /dev/null &"
|
||||
write_runner_cmd+="(/bin/bash $(shell_quote "$runner_path") > $(shell_quote "$log_path") 2>&1 < /dev/null &) >/dev/null 2>&1"
|
||||
guest_current_user_sh "$write_runner_cmd"
|
||||
guest_home="$(resolve_guest_current_user_home)"
|
||||
guest_log_state_path="$(mktemp "${TMPDIR:-/tmp}/openclaw-guest-log-state.XXXXXX")"
|
||||
latest_npm_log_state_path="$(mktemp "${TMPDIR:-/tmp}/openclaw-guest-npm-log-state.XXXXXX")"
|
||||
npm_state_path="$(mktemp "${TMPDIR:-/tmp}/openclaw-guest-npm-log-path.XXXXXX")"
|
||||
: >"$guest_log_state_path"
|
||||
: >"$latest_npm_log_state_path"
|
||||
: >"$npm_state_path"
|
||||
deadline=$((SECONDS + timeout_s))
|
||||
while (( SECONDS < deadline )); do
|
||||
if guest_current_user_exec /bin/test -f "$done_path" >/dev/null 2>&1; then
|
||||
rc="$(guest_current_user_exec /bin/cat "$done_path" | tr -d '\r\n')"
|
||||
stream_guest_file_delta "$log_path" "$guest_log_state_path" ""
|
||||
latest_npm_log_path="$(latest_guest_npm_debug_log_path "$guest_home" || true)"
|
||||
if [[ -n "$latest_npm_log_path" ]]; then
|
||||
if [[ "$(cat "$npm_state_path" 2>/dev/null || true)" != "$latest_npm_log_path" ]]; then
|
||||
printf '%s\n' "$latest_npm_log_path" >"$npm_state_path"
|
||||
: >"$latest_npm_log_state_path"
|
||||
printf 'npm-debug: %s\n' "$latest_npm_log_path"
|
||||
fi
|
||||
stream_guest_file_delta "$latest_npm_log_path" "$latest_npm_log_state_path" "npm-debug: "
|
||||
fi
|
||||
rc="$(guest_runner_rc_from_log "$log_path" 2>/dev/null || true)"
|
||||
if [[ "$rc" =~ ^-?[0-9]+$ ]]; then
|
||||
guest_current_user_exec /bin/rm -f "$done_path" "$runner_path" >/dev/null 2>&1 || true
|
||||
stream_guest_file_delta "$log_path" "$guest_log_state_path" ""
|
||||
if [[ -n "$latest_npm_log_path" ]]; then
|
||||
stream_guest_file_delta "$latest_npm_log_path" "$latest_npm_log_state_path" "npm-debug: "
|
||||
fi
|
||||
rm -f "$guest_log_state_path" "$latest_npm_log_state_path" "$npm_state_path"
|
||||
[[ -n "$rc" ]] || rc=1
|
||||
return "$rc"
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
rm -f "$guest_log_state_path" "$latest_npm_log_state_path" "$npm_state_path"
|
||||
warn "guest script timed out after ${timeout_s}s"
|
||||
guest_current_user_tail_file "$log_path" 120 >&2 || true
|
||||
return 124
|
||||
@@ -937,6 +1070,12 @@ extract_package_build_commit_from_tgz() {
|
||||
|
||||
pack_main_tgz() {
|
||||
local short_head pkg packed_commit
|
||||
if target_package_installs_directly; then
|
||||
say "Use direct guest install for target package spec: $TARGET_PACKAGE_SPEC"
|
||||
TARGET_EXPECT_VERSION="$(npm view "$TARGET_PACKAGE_SPEC" version --userconfig "$(mktemp)")"
|
||||
say "Target package version: $TARGET_EXPECT_VERSION"
|
||||
return
|
||||
fi
|
||||
if [[ -n "$TARGET_PACKAGE_SPEC" ]]; then
|
||||
say "Pack target package tgz: $TARGET_PACKAGE_SPEC"
|
||||
pkg="$(
|
||||
@@ -1049,17 +1188,38 @@ start_server() {
|
||||
kill -0 "$SERVER_PID" >/dev/null 2>&1 || die "failed to start host HTTP server"
|
||||
}
|
||||
|
||||
install_main_timeout() {
|
||||
if target_package_installs_directly; then
|
||||
printf '%s\n' "$TIMEOUT_INSTALL_REGISTRY_S"
|
||||
return
|
||||
fi
|
||||
printf '%s\n' "$TIMEOUT_INSTALL_TGZ_S"
|
||||
}
|
||||
|
||||
install_main_tgz() {
|
||||
local host_ip="$1"
|
||||
local temp_name="$2"
|
||||
local tgz_url_q
|
||||
local install_done install_log install_runner tgz_url_q
|
||||
install_log="/tmp/${temp_name}.log"
|
||||
install_done="/tmp/${temp_name}.done"
|
||||
install_runner="/tmp/${temp_name}.runner.sh"
|
||||
if target_package_installs_directly; then
|
||||
run_logged_guest_current_user_sh "$(cat <<EOF
|
||||
printf 'install-source: registry-spec %s\n' $(shell_quote "$TARGET_PACKAGE_SPEC")
|
||||
$GUEST_NPM_BIN install -g $(shell_quote "$TARGET_PACKAGE_SPEC")
|
||||
$GUEST_OPENCLAW_BIN --version
|
||||
EOF
|
||||
)" "$install_log" "$install_done" "$(install_main_timeout)" "$install_runner"
|
||||
return
|
||||
fi
|
||||
tgz_url_q="$(shell_quote "http://$host_ip:$HOST_PORT/$(basename "$MAIN_TGZ_PATH")")"
|
||||
guest_current_user_sh "$(cat <<EOF
|
||||
run_logged_guest_current_user_sh "$(cat <<EOF
|
||||
printf 'install-source: host-tgz %s\n' $(shell_quote "$tgz_url_q")
|
||||
curl -fsSL $tgz_url_q -o /tmp/$temp_name
|
||||
$GUEST_NPM_BIN install -g /tmp/$temp_name
|
||||
$GUEST_OPENCLAW_BIN --version
|
||||
EOF
|
||||
)"
|
||||
)" "$install_log" "$install_done" "$(install_main_timeout)" "$install_runner"
|
||||
}
|
||||
|
||||
verify_bundle_permissions() {
|
||||
@@ -1562,7 +1722,7 @@ run_fresh_main_lane() {
|
||||
local snapshot_id="$1"
|
||||
local host_ip="$2"
|
||||
phase_run "fresh.restore-snapshot" "$TIMEOUT_SNAPSHOT_S" restore_snapshot "$snapshot_id"
|
||||
phase_run "fresh.install-main" "$TIMEOUT_INSTALL_S" install_main_tgz "$host_ip" "openclaw-main-fresh.tgz"
|
||||
phase_run "fresh.install-main" "$(install_main_timeout)" install_main_tgz "$host_ip" "openclaw-main-fresh.tgz"
|
||||
FRESH_MAIN_VERSION="$(extract_last_version "$(phase_log_path fresh.install-main)")"
|
||||
phase_run "fresh.verify-main-version" "$TIMEOUT_VERIFY_S" verify_target_version
|
||||
phase_run "fresh.verify-bundle-permissions" "$TIMEOUT_PERMISSION_S" verify_bundle_permissions
|
||||
@@ -1586,7 +1746,7 @@ run_upgrade_lane() {
|
||||
local snapshot_id="$1"
|
||||
local host_ip="$2"
|
||||
phase_run "upgrade.restore-snapshot" "$TIMEOUT_SNAPSHOT_S" restore_snapshot "$snapshot_id"
|
||||
phase_run "upgrade.install-latest" "$TIMEOUT_INSTALL_S" install_latest_release
|
||||
phase_run "upgrade.install-latest" "$TIMEOUT_INSTALL_SITE_S" install_latest_release
|
||||
LATEST_INSTALLED_VERSION="$(extract_last_version "$(phase_log_path upgrade.install-latest)")"
|
||||
phase_run "upgrade.verify-latest-version" "$TIMEOUT_VERIFY_S" verify_version_contains "$LATEST_VERSION"
|
||||
if [[ "$CHECK_LATEST_REF" -eq 1 ]]; then
|
||||
@@ -1599,7 +1759,7 @@ run_upgrade_lane() {
|
||||
UPGRADE_PRECHECK_STATUS="skipped"
|
||||
fi
|
||||
if upgrade_uses_host_tgz; then
|
||||
phase_run "upgrade.install-main" "$TIMEOUT_INSTALL_S" install_main_tgz "$host_ip" "openclaw-main-upgrade.tgz"
|
||||
phase_run "upgrade.install-main" "$(install_main_timeout)" install_main_tgz "$host_ip" "openclaw-main-upgrade.tgz"
|
||||
UPGRADE_MAIN_VERSION="$(extract_last_version "$(phase_log_path upgrade.install-main)")"
|
||||
phase_run "upgrade.verify-main-version" "$TIMEOUT_VERIFY_S" verify_target_version
|
||||
phase_run "upgrade.verify-bundle-permissions" "$TIMEOUT_PERMISSION_S" verify_bundle_permissions
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/e2e/lib/parallels-macos-common.sh"
|
||||
|
||||
MACOS_VM="macOS Tahoe"
|
||||
WINDOWS_VM="Windows 11"
|
||||
@@ -755,55 +756,8 @@ raise SystemExit(completed.returncode)
|
||||
PY
|
||||
}
|
||||
|
||||
resolve_macos_desktop_user() {
|
||||
local user
|
||||
user="$(prlctl exec "$MACOS_VM" /usr/bin/stat -f '%Su' /dev/console 2>/dev/null | tr -d '\r' | tail -n 1 || true)"
|
||||
if [[ "$user" =~ ^[A-Za-z0-9._-]+$ && "$user" != "root" && "$user" != "loginwindow" ]]; then
|
||||
printf '%s\n' "$user"
|
||||
return 0
|
||||
fi
|
||||
prlctl exec "$MACOS_VM" /usr/bin/dscl . -list /Users NFSHomeDirectory 2>/dev/null \
|
||||
| tr -d '\r' \
|
||||
| awk '$2 ~ /^\/Users\// && $1 !~ /^_/ && $1 != "Shared" && $1 != ".localized" { print $1; exit }'
|
||||
}
|
||||
|
||||
resolve_macos_desktop_home() {
|
||||
local user="$1"
|
||||
local home
|
||||
home="$(
|
||||
prlctl exec "$MACOS_VM" /usr/bin/dscl . -read "/Users/$user" NFSHomeDirectory 2>/dev/null \
|
||||
| tr -d '\r' \
|
||||
| awk '/NFSHomeDirectory:/ { print $2; exit }'
|
||||
)"
|
||||
if [[ -n "$home" ]]; then
|
||||
printf '%s\n' "$home"
|
||||
else
|
||||
printf '/Users/%s\n' "$user"
|
||||
fi
|
||||
}
|
||||
|
||||
macos_current_user_available() {
|
||||
prlctl exec "$MACOS_VM" --current-user /usr/bin/whoami >/dev/null 2>&1
|
||||
}
|
||||
|
||||
macos_desktop_user_exec() {
|
||||
if macos_current_user_available; then
|
||||
prlctl exec "$MACOS_VM" --current-user /usr/bin/env "$API_KEY_ENV=$API_KEY_VALUE" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
local user home
|
||||
user="$(resolve_macos_desktop_user)"
|
||||
[[ -n "$user" ]] || die "unable to resolve macOS desktop user for sudo fallback"
|
||||
home="$(resolve_macos_desktop_home "$user")"
|
||||
warn "macOS --current-user unavailable; using root sudo fallback for $user"
|
||||
prlctl exec "$MACOS_VM" /usr/bin/sudo -u "$user" /usr/bin/env \
|
||||
"HOME=$home" \
|
||||
"USER=$user" \
|
||||
"LOGNAME=$user" \
|
||||
"PATH=/opt/homebrew/bin:/opt/homebrew/opt/node/bin:/opt/homebrew/sbin:/usr/bin:/bin:/usr/sbin:/sbin" \
|
||||
"$API_KEY_ENV=$API_KEY_VALUE" \
|
||||
"$@"
|
||||
parallels_macos_desktop_user_exec "$MACOS_VM" "$API_KEY_ENV" "$API_KEY_VALUE" "$@"
|
||||
}
|
||||
|
||||
guest_powershell_poll() {
|
||||
|
||||
Reference in New Issue
Block a user