mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-09 02:44:28 +02:00
test: add windows dev-update smoke lanes
This commit is contained in:
@@ -67,14 +67,20 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
|
||||
|
||||
- Preferred entrypoint: `pnpm test:parallels:windows`
|
||||
- Use the snapshot closest to `pre-openclaw-native-e2e-2026-03-12`.
|
||||
- Default upgrade coverage on Windows should now include: fresh snapshot -> site installer pinned to the requested stable tag -> `openclaw update --channel dev` on the guest. Keep the older host-tgz upgrade path only when the caller explicitly passes `--target-package-spec`.
|
||||
- Optional exact npm-tag baseline on Windows: `bash scripts/e2e/parallels-windows-smoke.sh --mode upgrade --target-package-spec openclaw@<tag> --json`. That lane installs the published npm tarball as baseline, then runs `openclaw update --channel dev`.
|
||||
- Optional forward-fix Windows validation: `bash scripts/e2e/parallels-windows-smoke.sh --mode upgrade --upgrade-from-packed-main --json`. That lane installs the packed current-main npm tgz as baseline, then runs `openclaw update --channel dev`.
|
||||
- Always use `prlctl exec --current-user`; plain `prlctl exec` lands in `NT AUTHORITY\\SYSTEM`.
|
||||
- Prefer explicit `npm.cmd` and `openclaw.cmd`.
|
||||
- Use PowerShell only as the transport with `-ExecutionPolicy Bypass`, then call the `.cmd` shims from inside it.
|
||||
- Current Windows Node installs expose `corepack` as a `.cmd` shim. If a release-to-dev lane sees `corepack` on PATH but `openclaw update --channel dev` still behaves as if corepack is missing, treat that as an exec-shim regression first.
|
||||
- If an exact published-tag Windows lane fails during preflight with `npm run build` and `'pnpm' is not recognized`, remember that the guest is still executing the old published updater. Validate the fix with `--upgrade-from-packed-main`, then wait for the next tagged npm release before expecting the historical tag lane to pass.
|
||||
- Multi-word `openclaw agent --message ...` checks should call `& $openclaw ...` inside PowerShell, not `Start-Process ... -ArgumentList` against `openclaw.cmd`, or Commander can see split argv and throw `too many arguments for 'agent'`.
|
||||
- Windows installer/tgz phases now retry once after guest-ready recheck; keep new Windows smoke steps idempotent so a transport-flake retry is safe.
|
||||
- If a Windows retry sees the VM become `suspended` or `stopped`, resume/start it before the next `prlctl exec`; otherwise the second attempt just repeats the same `rc=255`.
|
||||
- Windows global `npm install -g` phases can stay quiet for a minute or more even when healthy; inspect the phase log before calling it hung, and only treat it as a regression once the retry wrapper or timeout trips.
|
||||
- Fresh Windows tgz install phases should also use the background PowerShell runner plus done-file/log-drain pattern; do not rely on one long-lived `prlctl exec ... powershell ... npm install -g` transport for package installs.
|
||||
- Windows release-to-dev helpers should log `where pnpm` before and after the update and require `where pnpm` to succeed post-update. That proves the updater installed or enabled `pnpm` itself instead of depending on a smoke-only bootstrap.
|
||||
- Fresh Windows ref-mode onboard should use the same background PowerShell runner plus done-file/log-drain pattern as the npm-update helper, including startup materialization checks, host-side timeouts on short poll `prlctl exec` calls, and retry-on-poll-failure behavior for transient transport flakes.
|
||||
- Fresh Windows daemon-health reachability should use a hello-only gateway probe and a longer per-probe timeout than the default local attach path; full health RPCs are too eager during initial startup on current main.
|
||||
- Fresh Windows ref-mode agent verification should set `OPENAI_API_KEY` in the PowerShell environment before invoking `openclaw.cmd agent`, for the same pairing-required fallback reason as macOS.
|
||||
|
||||
@@ -16,6 +16,7 @@ HOST_IP=""
|
||||
LATEST_VERSION=""
|
||||
INSTALL_VERSION=""
|
||||
TARGET_PACKAGE_SPEC=""
|
||||
UPGRADE_FROM_PACKED_MAIN=0
|
||||
JSON_OUTPUT=0
|
||||
KEEP_SERVER=0
|
||||
CHECK_LATEST_REF=1
|
||||
@@ -28,8 +29,11 @@ MAIN_TGZ_DIR="$(mktemp -d)"
|
||||
MAIN_TGZ_PATH=""
|
||||
MINGIT_ZIP_PATH=""
|
||||
MINGIT_ZIP_NAME=""
|
||||
WINDOWS_LATEST_INSTALL_SCRIPT_PATH=""
|
||||
WINDOWS_BASELINE_INSTALL_SCRIPT_PATH=""
|
||||
WINDOWS_INSTALL_SCRIPT_PATH=""
|
||||
WINDOWS_ONBOARD_SCRIPT_PATH=""
|
||||
WINDOWS_DEV_UPDATE_SCRIPT_PATH=""
|
||||
SERVER_PID=""
|
||||
RUN_DIR="$(mktemp -d /tmp/openclaw-parallels-windows.XXXXXX)"
|
||||
BUILD_LOCK_DIR="${TMPDIR:-/tmp}/openclaw-parallels-build.lock"
|
||||
@@ -58,13 +62,41 @@ say() {
|
||||
}
|
||||
|
||||
artifact_label() {
|
||||
if [[ "$TARGET_PACKAGE_SPEC" == "" && "$MODE" == "upgrade" && "$UPGRADE_FROM_PACKED_MAIN" -eq 0 ]]; then
|
||||
printf 'Windows smoke artifacts'
|
||||
return
|
||||
fi
|
||||
if [[ -n "$TARGET_PACKAGE_SPEC" ]]; then
|
||||
printf 'target package tgz'
|
||||
printf 'baseline package tgz'
|
||||
return
|
||||
fi
|
||||
if [[ "$UPGRADE_FROM_PACKED_MAIN" -eq 1 ]]; then
|
||||
printf 'packed main tgz'
|
||||
return
|
||||
fi
|
||||
printf 'current main tgz'
|
||||
}
|
||||
|
||||
upgrade_uses_host_tgz() {
|
||||
[[ "$UPGRADE_FROM_PACKED_MAIN" -eq 1 || -n "$TARGET_PACKAGE_SPEC" ]]
|
||||
}
|
||||
|
||||
needs_host_tgz() {
|
||||
[[ "$MODE" == "fresh" || "$MODE" == "both" ]] || upgrade_uses_host_tgz
|
||||
}
|
||||
|
||||
upgrade_summary_label() {
|
||||
if [[ -n "$TARGET_PACKAGE_SPEC" ]]; then
|
||||
printf 'target-package->dev'
|
||||
return
|
||||
fi
|
||||
if [[ "$UPGRADE_FROM_PACKED_MAIN" -eq 1 ]]; then
|
||||
printf 'packed-main->dev'
|
||||
return
|
||||
fi
|
||||
printf 'latest->dev'
|
||||
}
|
||||
|
||||
extract_package_build_commit_from_tgz() {
|
||||
tar -xOf "$1" package/dist/build-info.json | python3 -c 'import json, sys; print(json.load(sys.stdin).get("commit", ""))'
|
||||
}
|
||||
@@ -106,9 +138,15 @@ Options:
|
||||
--host-ip <ip> Override Parallels host IP.
|
||||
--latest-version <ver> Override npm latest version lookup.
|
||||
--install-version <ver> Pin site-installer version/dist-tag for the baseline lane.
|
||||
--upgrade-from-packed-main
|
||||
Upgrade lane: install the packed current-main npm tgz as baseline,
|
||||
then run openclaw update --channel dev.
|
||||
--target-package-spec <npm-spec>
|
||||
Install this npm package tarball instead of packing current main.
|
||||
Upgrade lane: install this npm package tarball as the baseline,
|
||||
then run openclaw update --channel dev.
|
||||
Fresh lane: install this npm package tarball instead of packing current main.
|
||||
Example: openclaw@2026.3.13-beta.1
|
||||
Default upgrade lane without this flag: latest/site installer -> dev channel update.
|
||||
--skip-latest-ref-check Skip latest-release ref-mode precheck.
|
||||
--keep-server Leave temp host HTTP server running.
|
||||
--json Print machine-readable JSON summary.
|
||||
@@ -162,6 +200,10 @@ while [[ $# -gt 0 ]]; do
|
||||
INSTALL_VERSION="$2"
|
||||
shift 2
|
||||
;;
|
||||
--upgrade-from-packed-main)
|
||||
UPGRADE_FROM_PACKED_MAIN=1
|
||||
shift
|
||||
;;
|
||||
--target-package-spec)
|
||||
TARGET_PACKAGE_SPEC="$2"
|
||||
shift 2
|
||||
@@ -653,6 +695,14 @@ resolve_latest_version() {
|
||||
npm view openclaw version --userconfig "$(mktemp)"
|
||||
}
|
||||
|
||||
baseline_install_version() {
|
||||
if [[ -n "$INSTALL_VERSION" ]]; then
|
||||
printf '%s\n' "$INSTALL_VERSION"
|
||||
return
|
||||
fi
|
||||
printf '%s\n' "$LATEST_VERSION"
|
||||
}
|
||||
|
||||
resolve_mingit_download() {
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
@@ -778,19 +828,24 @@ EOF
|
||||
)"
|
||||
}
|
||||
|
||||
ensure_mingit_zip() {
|
||||
local mingit_name mingit_url
|
||||
mapfile -t mingit_meta < <(resolve_mingit_download)
|
||||
mingit_name="${mingit_meta[0]}"
|
||||
mingit_url="${mingit_meta[1]}"
|
||||
MINGIT_ZIP_NAME="$mingit_name"
|
||||
MINGIT_ZIP_PATH="$MAIN_TGZ_DIR/$mingit_name"
|
||||
if [[ ! -f "$MINGIT_ZIP_PATH" ]]; then
|
||||
say "Download $MINGIT_ZIP_NAME"
|
||||
curl -fsSL "$mingit_url" -o "$MINGIT_ZIP_PATH"
|
||||
fi
|
||||
}
|
||||
|
||||
pack_main_tgz() {
|
||||
local mingit_name mingit_url short_head pkg packed_commit
|
||||
local short_head pkg packed_commit
|
||||
ensure_mingit_zip
|
||||
if [[ -n "$TARGET_PACKAGE_SPEC" ]]; then
|
||||
say "Pack target package tgz: $TARGET_PACKAGE_SPEC"
|
||||
mapfile -t mingit_meta < <(resolve_mingit_download)
|
||||
mingit_name="${mingit_meta[0]}"
|
||||
mingit_url="${mingit_meta[1]}"
|
||||
MINGIT_ZIP_NAME="$mingit_name"
|
||||
MINGIT_ZIP_PATH="$MAIN_TGZ_DIR/$mingit_name"
|
||||
if [[ ! -f "$MINGIT_ZIP_PATH" ]]; then
|
||||
say "Download $MINGIT_ZIP_NAME"
|
||||
curl -fsSL "$mingit_url" -o "$MINGIT_ZIP_PATH"
|
||||
fi
|
||||
pkg="$(
|
||||
npm pack "$TARGET_PACKAGE_SPEC" --ignore-scripts --json --pack-destination "$MAIN_TGZ_DIR" \
|
||||
| python3 -c 'import json, sys; data = json.load(sys.stdin); print(data[-1]["filename"])'
|
||||
@@ -803,15 +858,6 @@ pack_main_tgz() {
|
||||
fi
|
||||
say "Pack current main tgz"
|
||||
ensure_current_build
|
||||
mapfile -t mingit_meta < <(resolve_mingit_download)
|
||||
mingit_name="${mingit_meta[0]}"
|
||||
mingit_url="${mingit_meta[1]}"
|
||||
MINGIT_ZIP_NAME="$mingit_name"
|
||||
MINGIT_ZIP_PATH="$MAIN_TGZ_DIR/$mingit_name"
|
||||
if [[ ! -f "$MINGIT_ZIP_PATH" ]]; then
|
||||
say "Download $MINGIT_ZIP_NAME"
|
||||
curl -fsSL "$mingit_url" -o "$MINGIT_ZIP_PATH"
|
||||
fi
|
||||
short_head="$(git rev-parse --short HEAD)"
|
||||
pkg="$(
|
||||
npm pack --ignore-scripts --json --pack-destination "$MAIN_TGZ_DIR" \
|
||||
@@ -838,7 +884,11 @@ verify_target_version() {
|
||||
start_server() {
|
||||
local host_ip="$1"
|
||||
local artifact probe_url attempt
|
||||
artifact="$(basename "$MAIN_TGZ_PATH")"
|
||||
if [[ -n "$MAIN_TGZ_PATH" ]]; then
|
||||
artifact="$(basename "$MAIN_TGZ_PATH")"
|
||||
else
|
||||
artifact="$MINGIT_ZIP_NAME"
|
||||
fi
|
||||
attempt=0
|
||||
while :; do
|
||||
attempt=$((attempt + 1))
|
||||
@@ -864,22 +914,372 @@ start_server() {
|
||||
done
|
||||
}
|
||||
|
||||
write_latest_install_runner_script() {
|
||||
local install_url_q="$1"
|
||||
local version_flag_q="$2"
|
||||
WINDOWS_LATEST_INSTALL_SCRIPT_PATH="$MAIN_TGZ_DIR/openclaw-install-latest.ps1"
|
||||
cat >"$WINDOWS_LATEST_INSTALL_SCRIPT_PATH" <<EOF
|
||||
param(
|
||||
[Parameter(Mandatory = \$true)][string]\$LogPath,
|
||||
[Parameter(Mandatory = \$true)][string]\$DonePath
|
||||
)
|
||||
|
||||
\$ErrorActionPreference = 'Stop'
|
||||
\$PSNativeCommandUseErrorActionPreference = \$false
|
||||
|
||||
function Write-ProgressLog {
|
||||
param([Parameter(Mandatory = \$true)][string]\$Stage)
|
||||
|
||||
"==> \$Stage" | Tee-Object -FilePath \$LogPath -Append | Out-Null
|
||||
}
|
||||
|
||||
try {
|
||||
\$script = Invoke-RestMethod -Uri '$install_url_q'
|
||||
Write-ProgressLog 'install.start'
|
||||
& ([scriptblock]::Create(\$script)) ${version_flag_q}-NoOnboard *>&1 | Tee-Object -FilePath \$LogPath -Append | Out-Null
|
||||
if (\$LASTEXITCODE -ne 0) {
|
||||
throw "installer failed with exit code \$LASTEXITCODE"
|
||||
}
|
||||
Write-ProgressLog 'install.version'
|
||||
& (Join-Path \$env:APPDATA 'npm\openclaw.cmd') --version *>&1 | Tee-Object -FilePath \$LogPath -Append | Out-Null
|
||||
if (\$LASTEXITCODE -ne 0) {
|
||||
throw "openclaw --version failed with exit code \$LASTEXITCODE"
|
||||
}
|
||||
Set-Content -Path \$DonePath -Value ([string]0)
|
||||
exit 0
|
||||
} catch {
|
||||
if (Test-Path \$LogPath) {
|
||||
Add-Content -Path \$LogPath -Value (\$_ | Out-String)
|
||||
} else {
|
||||
(\$_ | Out-String) | Set-Content -Path \$LogPath
|
||||
}
|
||||
Set-Content -Path \$DonePath -Value '1'
|
||||
exit 1
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
write_baseline_npm_install_runner_script() {
|
||||
WINDOWS_BASELINE_INSTALL_SCRIPT_PATH="$MAIN_TGZ_DIR/openclaw-install-baseline-npm.ps1"
|
||||
cat >"$WINDOWS_BASELINE_INSTALL_SCRIPT_PATH" <<'EOF'
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Version,
|
||||
[Parameter(Mandatory = $true)][string]$LogPath,
|
||||
[Parameter(Mandatory = $true)][string]$DonePath
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$PSNativeCommandUseErrorActionPreference = $false
|
||||
|
||||
function Write-ProgressLog {
|
||||
param([Parameter(Mandatory = $true)][string]$Stage)
|
||||
|
||||
"==> $Stage" | Tee-Object -FilePath $LogPath -Append | Out-Null
|
||||
}
|
||||
|
||||
function Invoke-Logged {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Label,
|
||||
[Parameter(Mandatory = $true)][scriptblock]$Command
|
||||
)
|
||||
|
||||
$output = $null
|
||||
$previousErrorActionPreference = $ErrorActionPreference
|
||||
$previousNativeErrorPreference = $PSNativeCommandUseErrorActionPreference
|
||||
try {
|
||||
$ErrorActionPreference = 'Continue'
|
||||
$PSNativeCommandUseErrorActionPreference = $false
|
||||
$output = & $Command *>&1
|
||||
$exitCode = $LASTEXITCODE
|
||||
} finally {
|
||||
$ErrorActionPreference = $previousErrorActionPreference
|
||||
$PSNativeCommandUseErrorActionPreference = $previousNativeErrorPreference
|
||||
}
|
||||
|
||||
if ($null -ne $output) {
|
||||
$output | Tee-Object -FilePath $LogPath -Append | Out-Null
|
||||
}
|
||||
|
||||
if ($exitCode -ne 0) {
|
||||
throw "$Label failed with exit code $exitCode"
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$portableGit = Join-Path (Join-Path (Join-Path $env:LOCALAPPDATA 'OpenClaw\deps') 'portable-git') ''
|
||||
$env:PATH = "$portableGit\cmd;$portableGit\mingw64\bin;$portableGit\usr\bin;$env:PATH"
|
||||
$openclaw = Join-Path $env:APPDATA 'npm\openclaw.cmd'
|
||||
|
||||
Write-ProgressLog 'install.start'
|
||||
Invoke-Logged 'npm install baseline release' {
|
||||
& npm.cmd install -g "openclaw@$Version" --no-fund --no-audit --loglevel=error
|
||||
}
|
||||
|
||||
Write-ProgressLog 'install.version'
|
||||
Invoke-Logged 'openclaw --version' { & $openclaw --version }
|
||||
|
||||
Set-Content -Path $DonePath -Value ([string]0)
|
||||
exit 0
|
||||
} catch {
|
||||
if (Test-Path $LogPath) {
|
||||
Add-Content -Path $LogPath -Value ($_ | Out-String)
|
||||
} else {
|
||||
($_ | Out-String) | Set-Content -Path $LogPath
|
||||
}
|
||||
Set-Content -Path $DonePath -Value '1'
|
||||
exit 1
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
install_baseline_npm_release() {
|
||||
local host_ip="$1"
|
||||
local version="$2"
|
||||
local script_url
|
||||
local runner_name log_name done_name done_status launcher_state guest_log
|
||||
local log_state_path
|
||||
local start_seconds poll_deadline startup_checked poll_rc state_rc log_rc
|
||||
|
||||
write_baseline_npm_install_runner_script
|
||||
script_url="http://$host_ip:$HOST_PORT/$(basename "$WINDOWS_BASELINE_INSTALL_SCRIPT_PATH")"
|
||||
runner_name="openclaw-install-baseline-$RANDOM-$RANDOM.ps1"
|
||||
log_name="openclaw-install-baseline-$RANDOM-$RANDOM.log"
|
||||
done_name="openclaw-install-baseline-$RANDOM-$RANDOM.done"
|
||||
log_state_path="$(mktemp "${TMPDIR:-/tmp}/openclaw-install-baseline-log-state.XXXXXX")"
|
||||
: >"$log_state_path"
|
||||
start_seconds="$SECONDS"
|
||||
poll_deadline=$((SECONDS + TIMEOUT_INSTALL_S + 60))
|
||||
startup_checked=0
|
||||
|
||||
guest_powershell_poll 20 "$(cat <<EOF
|
||||
\$runner = Join-Path \$env:TEMP '$runner_name'
|
||||
\$log = Join-Path \$env:TEMP '$log_name'
|
||||
\$done = Join-Path \$env:TEMP '$done_name'
|
||||
Remove-Item \$runner, \$log, \$done -Force -ErrorAction SilentlyContinue
|
||||
curl.exe -fsSL '$script_url' -o \$runner
|
||||
Start-Process powershell.exe -ArgumentList @(
|
||||
'-NoProfile',
|
||||
'-ExecutionPolicy', 'Bypass',
|
||||
'-File', \$runner,
|
||||
'-Version', '$version',
|
||||
'-LogPath', \$log,
|
||||
'-DonePath', \$done
|
||||
) -WindowStyle Hidden | Out-Null
|
||||
EOF
|
||||
)"
|
||||
|
||||
stream_windows_baseline_install_log() {
|
||||
set +e
|
||||
guest_log="$(
|
||||
guest_powershell_poll 20 "\$log = Join-Path \$env:TEMP '$log_name'; if (Test-Path \$log) { Get-Content \$log }"
|
||||
)"
|
||||
log_rc=$?
|
||||
set -e
|
||||
if [[ $log_rc -ne 0 ]] || [[ -z "$guest_log" ]]; then
|
||||
return "$log_rc"
|
||||
fi
|
||||
GUEST_LOG="$guest_log" python3 - "$log_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")
|
||||
current = os.environ["GUEST_LOG"].replace("\r\n", "\n").replace("\r", "\n")
|
||||
|
||||
if current.startswith(previous):
|
||||
sys.stdout.write(current[len(previous):])
|
||||
else:
|
||||
sys.stdout.write(current)
|
||||
|
||||
state_path.write_text(current, encoding="utf-8")
|
||||
PY
|
||||
}
|
||||
|
||||
while :; do
|
||||
set +e
|
||||
done_status="$(
|
||||
guest_powershell_poll 20 "\$done = Join-Path \$env:TEMP '$done_name'; if (Test-Path \$done) { (Get-Content \$done -Raw).Trim() }"
|
||||
)"
|
||||
poll_rc=$?
|
||||
set -e
|
||||
done_status="${done_status//$'\r'/}"
|
||||
if [[ $poll_rc -ne 0 ]]; then
|
||||
warn "windows baseline install helper poll failed; retrying"
|
||||
if (( SECONDS >= poll_deadline )); then
|
||||
warn "windows baseline install helper timed out while polling done file"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
continue
|
||||
fi
|
||||
set +e
|
||||
stream_windows_baseline_install_log
|
||||
log_rc=$?
|
||||
set -e
|
||||
if [[ $log_rc -ne 0 ]]; then
|
||||
warn "windows baseline install helper live log poll failed; retrying"
|
||||
fi
|
||||
if [[ -n "$done_status" ]]; then
|
||||
if ! stream_windows_baseline_install_log; then
|
||||
warn "windows baseline install helper log drain failed after completion"
|
||||
fi
|
||||
rm -f "$log_state_path"
|
||||
[[ "$done_status" == "0" ]]
|
||||
return $?
|
||||
fi
|
||||
if [[ "$startup_checked" -eq 0 && $((SECONDS - start_seconds)) -ge 20 ]]; then
|
||||
set +e
|
||||
launcher_state="$(
|
||||
guest_powershell_poll 20 "\$runner = Join-Path \$env:TEMP '$runner_name'; \$log = Join-Path \$env:TEMP '$log_name'; \$done = Join-Path \$env:TEMP '$done_name'; 'runner=' + (Test-Path \$runner) + ' log=' + (Test-Path \$log) + ' done=' + (Test-Path \$done)"
|
||||
)"
|
||||
state_rc=$?
|
||||
set -e
|
||||
launcher_state="${launcher_state//$'\r'/}"
|
||||
startup_checked=1
|
||||
if [[ $state_rc -eq 0 && "$launcher_state" == *"runner=False"* && "$launcher_state" == *"log=False"* && "$launcher_state" == *"done=False"* ]]; then
|
||||
warn "windows baseline install helper failed to materialize guest files"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if (( SECONDS >= poll_deadline )); then
|
||||
if ! stream_windows_baseline_install_log; then
|
||||
warn "windows baseline install helper log drain failed after timeout"
|
||||
fi
|
||||
warn "windows baseline install helper timed out waiting for done file"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
}
|
||||
|
||||
install_latest_release() {
|
||||
local install_url_q version_flag_q
|
||||
local script_url
|
||||
local runner_name log_name done_name done_status launcher_state guest_log
|
||||
local log_state_path
|
||||
local start_seconds poll_deadline startup_checked poll_rc state_rc log_rc
|
||||
install_url_q="$(ps_single_quote "$INSTALL_URL")"
|
||||
version_flag_q=""
|
||||
if [[ -n "$INSTALL_VERSION" ]]; then
|
||||
version_flag_q="-Tag '$(ps_single_quote "$INSTALL_VERSION")' "
|
||||
fi
|
||||
local install_script
|
||||
install_script="$(cat <<EOF
|
||||
\$ProgressPreference = 'SilentlyContinue'
|
||||
\$script = Invoke-RestMethod -Uri '$install_url_q'
|
||||
& ([scriptblock]::Create(\$script)) ${version_flag_q}-NoOnboard
|
||||
& (Join-Path \$env:APPDATA 'npm\openclaw.cmd') --version
|
||||
write_latest_install_runner_script "$install_url_q" "$version_flag_q"
|
||||
script_url="http://$HOST_IP:$HOST_PORT/$(basename "$WINDOWS_LATEST_INSTALL_SCRIPT_PATH")"
|
||||
runner_name="openclaw-install-latest-$RANDOM-$RANDOM.ps1"
|
||||
log_name="openclaw-install-latest-$RANDOM-$RANDOM.log"
|
||||
done_name="openclaw-install-latest-$RANDOM-$RANDOM.done"
|
||||
log_state_path="$(mktemp "${TMPDIR:-/tmp}/openclaw-install-latest-log-state.XXXXXX")"
|
||||
: >"$log_state_path"
|
||||
start_seconds="$SECONDS"
|
||||
poll_deadline=$((SECONDS + TIMEOUT_INSTALL_S + 60))
|
||||
startup_checked=0
|
||||
|
||||
guest_powershell_poll 20 "$(cat <<EOF
|
||||
\$runner = Join-Path \$env:TEMP '$runner_name'
|
||||
\$log = Join-Path \$env:TEMP '$log_name'
|
||||
\$done = Join-Path \$env:TEMP '$done_name'
|
||||
Remove-Item \$runner, \$log, \$done -Force -ErrorAction SilentlyContinue
|
||||
curl.exe -fsSL '$script_url' -o \$runner
|
||||
Start-Process powershell.exe -ArgumentList @(
|
||||
'-NoProfile',
|
||||
'-ExecutionPolicy', 'Bypass',
|
||||
'-File', \$runner,
|
||||
'-LogPath', \$log,
|
||||
'-DonePath', \$done
|
||||
) -WindowStyle Hidden | Out-Null
|
||||
EOF
|
||||
)"
|
||||
run_windows_retry "latest release installer" 2 guest_powershell "$install_script"
|
||||
|
||||
stream_windows_latest_install_log() {
|
||||
set +e
|
||||
guest_log="$(
|
||||
guest_powershell_poll 20 "\$log = Join-Path \$env:TEMP '$log_name'; if (Test-Path \$log) { Get-Content \$log }"
|
||||
)"
|
||||
log_rc=$?
|
||||
set -e
|
||||
if [[ $log_rc -ne 0 ]] || [[ -z "$guest_log" ]]; then
|
||||
return "$log_rc"
|
||||
fi
|
||||
GUEST_LOG="$guest_log" python3 - "$log_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")
|
||||
current = os.environ["GUEST_LOG"].replace("\r\n", "\n").replace("\r", "\n")
|
||||
|
||||
if current.startswith(previous):
|
||||
sys.stdout.write(current[len(previous):])
|
||||
else:
|
||||
sys.stdout.write(current)
|
||||
|
||||
state_path.write_text(current, encoding="utf-8")
|
||||
PY
|
||||
}
|
||||
|
||||
while :; do
|
||||
set +e
|
||||
done_status="$(
|
||||
guest_powershell_poll 20 "\$done = Join-Path \$env:TEMP '$done_name'; if (Test-Path \$done) { (Get-Content \$done -Raw).Trim() }"
|
||||
)"
|
||||
poll_rc=$?
|
||||
set -e
|
||||
done_status="${done_status//$'\r'/}"
|
||||
if [[ $poll_rc -ne 0 ]]; then
|
||||
warn "windows latest install helper poll failed; retrying"
|
||||
if (( SECONDS >= poll_deadline )); then
|
||||
warn "windows latest install helper timed out while polling done file"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
continue
|
||||
fi
|
||||
set +e
|
||||
stream_windows_latest_install_log
|
||||
log_rc=$?
|
||||
set -e
|
||||
if [[ $log_rc -ne 0 ]]; then
|
||||
warn "windows latest install helper live log poll failed; retrying"
|
||||
fi
|
||||
if [[ -n "$done_status" ]]; then
|
||||
if ! stream_windows_latest_install_log; then
|
||||
warn "windows latest install helper log drain failed after completion"
|
||||
fi
|
||||
rm -f "$log_state_path"
|
||||
[[ "$done_status" == "0" ]]
|
||||
return $?
|
||||
fi
|
||||
if [[ "$startup_checked" -eq 0 && $((SECONDS - start_seconds)) -ge 20 ]]; then
|
||||
set +e
|
||||
launcher_state="$(
|
||||
guest_powershell_poll 20 "\$runner = Join-Path \$env:TEMP '$runner_name'; \$log = Join-Path \$env:TEMP '$log_name'; \$done = Join-Path \$env:TEMP '$done_name'; 'runner=' + (Test-Path \$runner) + ' log=' + (Test-Path \$log) + ' done=' + (Test-Path \$done)"
|
||||
)"
|
||||
state_rc=$?
|
||||
set -e
|
||||
launcher_state="${launcher_state//$'\r'/}"
|
||||
startup_checked=1
|
||||
if [[ $state_rc -eq 0 && "$launcher_state" == *"runner=False"* && "$launcher_state" == *"log=False"* && "$launcher_state" == *"done=False"* ]]; then
|
||||
warn "windows latest install helper failed to materialize guest files"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if (( SECONDS >= poll_deadline )); then
|
||||
if ! stream_windows_latest_install_log; then
|
||||
warn "windows latest install helper log drain failed after timeout"
|
||||
fi
|
||||
warn "windows latest install helper timed out waiting for done file"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
}
|
||||
|
||||
install_main_tgz() {
|
||||
@@ -901,7 +1301,7 @@ install_main_tgz() {
|
||||
poll_deadline=$((SECONDS + TIMEOUT_INSTALL_S + 60))
|
||||
startup_checked=0
|
||||
|
||||
guest_powershell "$(cat <<EOF
|
||||
guest_powershell_poll 20 "$(cat <<EOF
|
||||
\$runner = Join-Path \$env:TEMP '$runner_name'
|
||||
\$log = Join-Path \$env:TEMP '$log_name'
|
||||
\$done = Join-Path \$env:TEMP '$done_name'
|
||||
@@ -1007,6 +1407,246 @@ PY
|
||||
done
|
||||
}
|
||||
|
||||
write_dev_update_runner_script() {
|
||||
WINDOWS_DEV_UPDATE_SCRIPT_PATH="$MAIN_TGZ_DIR/openclaw-update-dev.ps1"
|
||||
cat >"$WINDOWS_DEV_UPDATE_SCRIPT_PATH" <<'EOF'
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$LogPath,
|
||||
[Parameter(Mandatory = $true)][string]$DonePath
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$PSNativeCommandUseErrorActionPreference = $false
|
||||
|
||||
function Write-ProgressLog {
|
||||
param([Parameter(Mandatory = $true)][string]$Stage)
|
||||
|
||||
"==> $Stage" | Tee-Object -FilePath $LogPath -Append | Out-Null
|
||||
}
|
||||
|
||||
function Write-LoggedLine {
|
||||
param([Parameter(Mandatory = $true)][string]$Line)
|
||||
|
||||
$Line | Tee-Object -FilePath $LogPath -Append | Out-Null
|
||||
}
|
||||
|
||||
function Invoke-Logged {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Label,
|
||||
[Parameter(Mandatory = $true)][scriptblock]$Command
|
||||
)
|
||||
|
||||
$output = $null
|
||||
$previousErrorActionPreference = $ErrorActionPreference
|
||||
$previousNativeErrorPreference = $PSNativeCommandUseErrorActionPreference
|
||||
try {
|
||||
$ErrorActionPreference = 'Continue'
|
||||
$PSNativeCommandUseErrorActionPreference = $false
|
||||
$output = & $Command *>&1
|
||||
$exitCode = $LASTEXITCODE
|
||||
} finally {
|
||||
$ErrorActionPreference = $previousErrorActionPreference
|
||||
$PSNativeCommandUseErrorActionPreference = $previousNativeErrorPreference
|
||||
}
|
||||
|
||||
if ($null -ne $output) {
|
||||
$output | Tee-Object -FilePath $LogPath -Append | Out-Null
|
||||
}
|
||||
|
||||
if ($exitCode -ne 0) {
|
||||
throw "$Label failed with exit code $exitCode"
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$portableGit = Join-Path (Join-Path (Join-Path $env:LOCALAPPDATA 'OpenClaw\deps') 'portable-git') ''
|
||||
$env:PATH = "$portableGit\cmd;$portableGit\mingw64\bin;$portableGit\usr\bin;$env:PATH"
|
||||
$openclaw = Join-Path $env:APPDATA 'npm\openclaw.cmd'
|
||||
$gitRoot = Join-Path $env:USERPROFILE 'openclaw'
|
||||
$gitEntry = Join-Path $gitRoot 'openclaw.mjs'
|
||||
|
||||
Remove-Item $LogPath, $DonePath -Force -ErrorAction SilentlyContinue
|
||||
Write-ProgressLog 'update.start'
|
||||
|
||||
Write-ProgressLog 'update.where-pnpm-pre'
|
||||
$pnpmPre = Get-Command pnpm -ErrorAction SilentlyContinue
|
||||
if ($null -ne $pnpmPre) {
|
||||
Write-LoggedLine $pnpmPre.Source
|
||||
} else {
|
||||
Write-LoggedLine 'pnpm=missing-pre'
|
||||
}
|
||||
|
||||
Write-ProgressLog 'update.where-corepack-pre'
|
||||
$corepackPre = Get-Command corepack -ErrorAction SilentlyContinue
|
||||
if ($null -ne $corepackPre) {
|
||||
Write-LoggedLine $corepackPre.Source
|
||||
Invoke-Logged 'corepack --version' { & corepack --version }
|
||||
} else {
|
||||
Write-LoggedLine 'corepack=missing-pre'
|
||||
}
|
||||
|
||||
Write-ProgressLog 'update.reset-git-root'
|
||||
if (Test-Path $gitRoot) {
|
||||
Remove-Item $gitRoot -Recurse -Force
|
||||
}
|
||||
|
||||
Write-ProgressLog 'update.run-dev'
|
||||
Invoke-Logged 'openclaw update --channel dev --yes --json' {
|
||||
& $openclaw update --channel dev --yes --json
|
||||
}
|
||||
|
||||
if (-not (Test-Path $gitEntry)) {
|
||||
throw "git entry missing after dev update: $gitEntry"
|
||||
}
|
||||
|
||||
Write-ProgressLog 'update.where-pnpm-post'
|
||||
$pnpmPost = Get-Command pnpm -ErrorAction SilentlyContinue
|
||||
if ($null -eq $pnpmPost) {
|
||||
throw 'pnpm missing after dev update'
|
||||
}
|
||||
Write-LoggedLine $pnpmPost.Source
|
||||
|
||||
Write-ProgressLog 'update.verify-post'
|
||||
Invoke-Logged 'git openclaw --version' { & node.exe $gitEntry --version }
|
||||
Invoke-Logged 'git openclaw update status --json' { & node.exe $gitEntry update status --json }
|
||||
|
||||
Write-ProgressLog 'update.done'
|
||||
Set-Content -Path $DonePath -Value ([string]0)
|
||||
exit 0
|
||||
} catch {
|
||||
if (Test-Path $LogPath) {
|
||||
Add-Content -Path $LogPath -Value ($_ | Out-String)
|
||||
} else {
|
||||
($_ | Out-String) | Set-Content -Path $LogPath
|
||||
}
|
||||
Set-Content -Path $DonePath -Value '1'
|
||||
exit 1
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
run_dev_channel_update() {
|
||||
local host_ip="$1"
|
||||
local script_url
|
||||
local runner_name log_name done_name done_status launcher_state guest_log
|
||||
local log_state_path
|
||||
local start_seconds poll_deadline startup_checked poll_rc state_rc log_rc
|
||||
|
||||
write_dev_update_runner_script
|
||||
script_url="http://$host_ip:$HOST_PORT/$(basename "$WINDOWS_DEV_UPDATE_SCRIPT_PATH")"
|
||||
runner_name="openclaw-update-dev-$RANDOM-$RANDOM.ps1"
|
||||
log_name="openclaw-update-dev-$RANDOM-$RANDOM.log"
|
||||
done_name="openclaw-update-dev-$RANDOM-$RANDOM.done"
|
||||
log_state_path="$(mktemp "${TMPDIR:-/tmp}/openclaw-update-dev-log-state.XXXXXX")"
|
||||
: >"$log_state_path"
|
||||
start_seconds="$SECONDS"
|
||||
poll_deadline=$((SECONDS + TIMEOUT_INSTALL_S + 60))
|
||||
startup_checked=0
|
||||
|
||||
guest_powershell "$(cat <<EOF
|
||||
\$runner = Join-Path \$env:TEMP '$runner_name'
|
||||
\$log = Join-Path \$env:TEMP '$log_name'
|
||||
\$done = Join-Path \$env:TEMP '$done_name'
|
||||
Remove-Item \$runner, \$log, \$done -Force -ErrorAction SilentlyContinue
|
||||
curl.exe -fsSL '$script_url' -o \$runner
|
||||
Start-Process powershell.exe -ArgumentList @(
|
||||
'-NoProfile',
|
||||
'-ExecutionPolicy', 'Bypass',
|
||||
'-File', \$runner,
|
||||
'-LogPath', \$log,
|
||||
'-DonePath', \$done
|
||||
) -WindowStyle Hidden | Out-Null
|
||||
EOF
|
||||
)"
|
||||
|
||||
stream_windows_dev_update_log() {
|
||||
set +e
|
||||
guest_log="$(
|
||||
guest_powershell_poll 20 "\$log = Join-Path \$env:TEMP '$log_name'; if (Test-Path \$log) { Get-Content \$log }"
|
||||
)"
|
||||
log_rc=$?
|
||||
set -e
|
||||
if [[ $log_rc -ne 0 ]] || [[ -z "$guest_log" ]]; then
|
||||
return "$log_rc"
|
||||
fi
|
||||
GUEST_LOG="$guest_log" python3 - "$log_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")
|
||||
current = os.environ["GUEST_LOG"].replace("\r\n", "\n").replace("\r", "\n")
|
||||
|
||||
if current.startswith(previous):
|
||||
sys.stdout.write(current[len(previous):])
|
||||
else:
|
||||
sys.stdout.write(current)
|
||||
|
||||
state_path.write_text(current, encoding="utf-8")
|
||||
PY
|
||||
}
|
||||
|
||||
while :; do
|
||||
set +e
|
||||
done_status="$(
|
||||
guest_powershell_poll 20 "\$done = Join-Path \$env:TEMP '$done_name'; if (Test-Path \$done) { (Get-Content \$done -Raw).Trim() }"
|
||||
)"
|
||||
poll_rc=$?
|
||||
set -e
|
||||
done_status="${done_status//$'\r'/}"
|
||||
if [[ $poll_rc -ne 0 ]]; then
|
||||
warn "windows dev update helper poll failed; retrying"
|
||||
if (( SECONDS >= poll_deadline )); then
|
||||
warn "windows dev update helper timed out while polling done file"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
continue
|
||||
fi
|
||||
set +e
|
||||
stream_windows_dev_update_log
|
||||
log_rc=$?
|
||||
set -e
|
||||
if [[ $log_rc -ne 0 ]]; then
|
||||
warn "windows dev update helper live log poll failed; retrying"
|
||||
fi
|
||||
if [[ -n "$done_status" ]]; then
|
||||
if ! stream_windows_dev_update_log; then
|
||||
warn "windows dev update helper log drain failed after completion"
|
||||
fi
|
||||
rm -f "$log_state_path"
|
||||
[[ "$done_status" == "0" ]]
|
||||
return $?
|
||||
fi
|
||||
if [[ "$startup_checked" -eq 0 && $((SECONDS - start_seconds)) -ge 20 ]]; then
|
||||
set +e
|
||||
launcher_state="$(
|
||||
guest_powershell_poll 20 "\$runner = Join-Path \$env:TEMP '$runner_name'; \$log = Join-Path \$env:TEMP '$log_name'; \$done = Join-Path \$env:TEMP '$done_name'; 'runner=' + (Test-Path \$runner) + ' log=' + (Test-Path \$log) + ' done=' + (Test-Path \$done)"
|
||||
)"
|
||||
state_rc=$?
|
||||
set -e
|
||||
launcher_state="${launcher_state//$'\r'/}"
|
||||
startup_checked=1
|
||||
if [[ $state_rc -eq 0 && "$launcher_state" == *"runner=False"* && "$launcher_state" == *"log=False"* && "$launcher_state" == *"done=False"* ]]; then
|
||||
warn "windows dev update helper failed to materialize guest files"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if (( SECONDS >= poll_deadline )); then
|
||||
if ! stream_windows_dev_update_log; then
|
||||
warn "windows dev update helper log drain failed after timeout"
|
||||
fi
|
||||
warn "windows dev update helper timed out waiting for done file"
|
||||
rm -f "$log_state_path"
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
}
|
||||
|
||||
write_install_runner_script() {
|
||||
WINDOWS_INSTALL_SCRIPT_PATH="$MAIN_TGZ_DIR/openclaw-install-main.ps1"
|
||||
cat >"$WINDOWS_INSTALL_SCRIPT_PATH" <<'EOF'
|
||||
@@ -1209,6 +1849,40 @@ verify_gateway() {
|
||||
guest_run_openclaw "" "" gateway status --deep --require-rpc
|
||||
}
|
||||
|
||||
verify_dev_channel_update() {
|
||||
local status_json pnpm_output
|
||||
status_json="$(
|
||||
guest_powershell "$(cat <<'EOF'
|
||||
$portableGit = Join-Path (Join-Path (Join-Path $env:LOCALAPPDATA 'OpenClaw\deps') 'portable-git') ''
|
||||
$env:PATH = "$portableGit\cmd;$portableGit\mingw64\bin;$portableGit\usr\bin;$env:PATH"
|
||||
$gitEntry = Join-Path (Join-Path $env:USERPROFILE 'openclaw') 'openclaw.mjs'
|
||||
if (-not (Test-Path $gitEntry)) {
|
||||
throw "git entry missing: $gitEntry"
|
||||
}
|
||||
& node.exe $gitEntry update status --json
|
||||
EOF
|
||||
)"
|
||||
)"
|
||||
pnpm_output="$(
|
||||
guest_powershell "$(cat <<'EOF'
|
||||
$portableGit = Join-Path (Join-Path (Join-Path $env:LOCALAPPDATA 'OpenClaw\deps') 'portable-git') ''
|
||||
$env:PATH = "$portableGit\cmd;$portableGit\mingw64\bin;$portableGit\usr\bin;$env:PATH"
|
||||
$pnpmCommand = Get-Command pnpm -ErrorAction SilentlyContinue
|
||||
if ($null -eq $pnpmCommand) {
|
||||
throw 'pnpm missing after dev update'
|
||||
}
|
||||
$pnpmCommand.Source
|
||||
EOF
|
||||
)"
|
||||
)"
|
||||
printf '%s\n' "$status_json"
|
||||
printf '%s\n' "$status_json" | grep -F '"installKind": "git"'
|
||||
printf '%s\n' "$status_json" | grep -F '"value": "dev"'
|
||||
printf '%s\n' "$status_json" | grep -F '"branch": "main"'
|
||||
printf '%s\n' "$pnpm_output"
|
||||
printf '%s\n' "$pnpm_output" | grep -Fi 'pnpm'
|
||||
}
|
||||
|
||||
run_gateway_daemon_action() {
|
||||
local action="$1"
|
||||
local runner_name log_name done_name done_status launcher_state
|
||||
@@ -1347,7 +2021,10 @@ run_fresh_main_lane() {
|
||||
local host_ip="$2"
|
||||
phase_run "fresh.restore-snapshot" "$TIMEOUT_SNAPSHOT_S" restore_snapshot "$snapshot_id" || return $?
|
||||
phase_run "fresh.wait-for-user" "$TIMEOUT_SNAPSHOT_S" wait_for_guest_ready || return $?
|
||||
phase_run "fresh.ensure-git" "$TIMEOUT_INSTALL_S" ensure_guest_git "$host_ip" || return $?
|
||||
if ! phase_run "fresh.ensure-git" "$TIMEOUT_INSTALL_S" ensure_guest_git "$host_ip"; then
|
||||
phase_run "fresh.wait-for-user-retry" "$TIMEOUT_SNAPSHOT_S" wait_for_guest_ready || return $?
|
||||
phase_run "fresh.ensure-git-retry" "$TIMEOUT_INSTALL_S" ensure_guest_git "$host_ip" || return $?
|
||||
fi
|
||||
phase_run "fresh.install-main" "$TIMEOUT_INSTALL_S" install_main_tgz "$host_ip" "openclaw-main-fresh.tgz" || return $?
|
||||
FRESH_MAIN_VERSION="$(extract_last_version "$(phase_log_path fresh.install-main)")"
|
||||
phase_run "fresh.verify-main-version" "$TIMEOUT_VERIFY_S" verify_target_version || return $?
|
||||
@@ -1361,11 +2038,23 @@ run_fresh_main_lane() {
|
||||
run_upgrade_lane() {
|
||||
local snapshot_id="$1"
|
||||
local host_ip="$2"
|
||||
local baseline_version
|
||||
baseline_version="$(baseline_install_version)"
|
||||
phase_run "upgrade.restore-snapshot" "$TIMEOUT_SNAPSHOT_S" restore_snapshot "$snapshot_id" || return $?
|
||||
phase_run "upgrade.wait-for-user" "$TIMEOUT_SNAPSHOT_S" wait_for_guest_ready || return $?
|
||||
phase_run "upgrade.install-latest" "$TIMEOUT_INSTALL_S" install_latest_release || return $?
|
||||
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" || return $?
|
||||
if ! phase_run "upgrade.ensure-git" "$TIMEOUT_INSTALL_S" ensure_guest_git "$host_ip"; then
|
||||
phase_run "upgrade.wait-for-user-retry" "$TIMEOUT_SNAPSHOT_S" wait_for_guest_ready || return $?
|
||||
phase_run "upgrade.ensure-git-retry" "$TIMEOUT_INSTALL_S" ensure_guest_git "$host_ip" || return $?
|
||||
fi
|
||||
if upgrade_uses_host_tgz; then
|
||||
phase_run "upgrade.install-baseline-package" "$TIMEOUT_INSTALL_S" install_main_tgz "$host_ip" "openclaw-main-upgrade.tgz" || return $?
|
||||
LATEST_INSTALLED_VERSION="$(extract_last_version "$(phase_log_path upgrade.install-baseline-package)")"
|
||||
phase_run "upgrade.verify-baseline-package-version" "$TIMEOUT_VERIFY_S" verify_target_version || return $?
|
||||
else
|
||||
phase_run "upgrade.install-baseline" "$TIMEOUT_INSTALL_S" install_baseline_npm_release "$host_ip" "$baseline_version" || return $?
|
||||
LATEST_INSTALLED_VERSION="$(extract_last_version "$(phase_log_path upgrade.install-baseline)")"
|
||||
phase_run "upgrade.verify-baseline-version" "$TIMEOUT_VERIFY_S" verify_version_contains "$baseline_version" || return $?
|
||||
fi
|
||||
if [[ "$CHECK_LATEST_REF" -eq 1 ]]; then
|
||||
if phase_run "upgrade.latest-ref-precheck" "$TIMEOUT_ONBOARD_PHASE_S" capture_latest_ref_failure; then
|
||||
UPGRADE_PRECHECK_STATUS="latest-ref-pass"
|
||||
@@ -1375,10 +2064,9 @@ run_upgrade_lane() {
|
||||
else
|
||||
UPGRADE_PRECHECK_STATUS="skipped"
|
||||
fi
|
||||
phase_run "upgrade.ensure-git" "$TIMEOUT_INSTALL_S" ensure_guest_git "$host_ip" || return $?
|
||||
phase_run "upgrade.install-main" "$TIMEOUT_INSTALL_S" install_main_tgz "$host_ip" "openclaw-main-upgrade.tgz" || return $?
|
||||
UPGRADE_MAIN_VERSION="$(extract_last_version "$(phase_log_path upgrade.install-main)")"
|
||||
phase_run "upgrade.verify-main-version" "$TIMEOUT_VERIFY_S" verify_target_version || return $?
|
||||
phase_run "upgrade.update-dev" "$TIMEOUT_INSTALL_S" run_dev_channel_update "$host_ip" || return $?
|
||||
UPGRADE_MAIN_VERSION="$(extract_last_version "$(phase_log_path upgrade.update-dev)")"
|
||||
phase_run "upgrade.verify-dev-channel" "$TIMEOUT_VERIFY_S" verify_dev_channel_update || return $?
|
||||
# Stop the old managed gateway before ref-mode onboard rewrites config and
|
||||
# gateway auth. Restarting first can leave the old token alive and make the
|
||||
# onboard health probe fail against a stale daemon.
|
||||
@@ -1404,7 +2092,11 @@ say "Latest npm version: $LATEST_VERSION"
|
||||
say "Current head: $(git rev-parse --short HEAD)"
|
||||
say "Run logs: $RUN_DIR"
|
||||
|
||||
pack_main_tgz
|
||||
if needs_host_tgz; then
|
||||
pack_main_tgz
|
||||
else
|
||||
ensure_mingit_zip
|
||||
fi
|
||||
start_server "$HOST_IP"
|
||||
|
||||
if [[ "$MODE" == "fresh" || "$MODE" == "both" ]]; then
|
||||
@@ -1467,12 +2159,15 @@ else
|
||||
if [[ -n "$TARGET_PACKAGE_SPEC" ]]; then
|
||||
printf ' target-package: %s\n' "$TARGET_PACKAGE_SPEC"
|
||||
fi
|
||||
if [[ "$UPGRADE_FROM_PACKED_MAIN" -eq 1 ]]; then
|
||||
printf ' upgrade-from-packed-main: yes\n'
|
||||
fi
|
||||
if [[ -n "$INSTALL_VERSION" ]]; then
|
||||
printf ' baseline-install-version: %s\n' "$INSTALL_VERSION"
|
||||
fi
|
||||
printf ' fresh-main: %s (%s)\n' "$FRESH_MAIN_STATUS" "$FRESH_MAIN_VERSION"
|
||||
printf ' latest->main precheck: %s (%s)\n' "$UPGRADE_PRECHECK_STATUS" "$LATEST_INSTALLED_VERSION"
|
||||
printf ' latest->main: %s (%s)\n' "$UPGRADE_STATUS" "$UPGRADE_MAIN_VERSION"
|
||||
printf ' %s precheck: %s (%s)\n' "$(upgrade_summary_label)" "$UPGRADE_PRECHECK_STATUS" "$LATEST_INSTALLED_VERSION"
|
||||
printf ' %s: %s (%s)\n' "$(upgrade_summary_label)" "$UPGRADE_STATUS" "$UPGRADE_MAIN_VERSION"
|
||||
printf ' logs: %s\n' "$RUN_DIR"
|
||||
printf ' summary: %s\n' "$SUMMARY_JSON_PATH"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user