mirror of https://github.com/openclaw/openclaw.git
fix: harden parallels smoke verification
This commit is contained in:
parent
a724246547
commit
923b316ddc
|
|
@ -45,6 +45,7 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
|
|||
- The macOS smoke should include a dashboard load phase after gateway health: resolve the tokenized URL with `openclaw dashboard --no-open`, verify the served HTML contains the Control UI title/root shell, then open Safari and require an established localhost TCP connection from Safari to the gateway port.
|
||||
- `prlctl exec` is fine for deterministic repo commands, but use the guest Terminal or `prlctl enter` when installer parity or shell-sensitive behavior matters.
|
||||
- Multi-word `openclaw agent --message ...` checks should go through a guest shell wrapper (`guest_current_user_sh` / `guest_current_user_cli` or `/bin/sh -lc ...`), not raw `prlctl exec ... node openclaw.mjs ...`, or the message can be split into extra argv tokens and Commander reports `too many arguments for 'agent'`.
|
||||
- When ref-mode onboarding stores `OPENAI_API_KEY` as an env secret ref, the post-onboard agent verification should also export `OPENAI_API_KEY` for the guest command. The gateway can still reject with pairing-required and fall back to embedded execution, and that fallback needs the env-backed credential available in the shell.
|
||||
- On the fresh Tahoe snapshot, `brew` exists but `node` may be missing from PATH in noninteractive exec. Use `/opt/homebrew/bin/node` when needed.
|
||||
- Fresh host-served tgz installs should install as guest root with `HOME=/var/root`, then run onboarding as the desktop user via `prlctl exec --current-user`.
|
||||
- Root-installed tgz smoke can log plugin blocks for world-writable `extensions/*`; do not treat that as an onboarding or gateway failure unless plugin loading is the task.
|
||||
|
|
@ -60,6 +61,8 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
|
|||
- Windows installer/tgz phases now retry once after guest-ready recheck; keep new Windows smoke steps idempotent so a transport-flake retry is safe.
|
||||
- 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 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 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.
|
||||
- The Windows upgrade smoke lane should restart the managed gateway after `upgrade.install-main` and before `upgrade.onboard-ref`, or the old process can keep the previous gateway token and fail `gateway-health` with `unauthorized: gateway token mismatch`.
|
||||
- Keep onboarding and status output ASCII-clean in logs; fancy punctuation becomes mojibake in current capture paths.
|
||||
- If you hit an older run with `rc=255` plus an empty `fresh.install-main.log` or `upgrade.install-main.log`, treat it as a likely `prlctl exec` transport drop after guest start-up, not immediate proof of an npm/package failure.
|
||||
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@ show_gateway_status_compat() {
|
|||
|
||||
verify_turn() {
|
||||
guest_current_user_cli \
|
||||
/usr/bin/env "OPENAI_API_KEY=$OPENAI_API_KEY_VALUE" \
|
||||
"$GUEST_OPENCLAW_BIN" agent \
|
||||
--agent main \
|
||||
--message "Reply with exact ASCII text OK only." \
|
||||
|
|
|
|||
|
|
@ -925,6 +925,100 @@ verify_gateway() {
|
|||
guest_run_openclaw "" "" gateway status --deep --require-rpc
|
||||
}
|
||||
|
||||
restart_gateway() {
|
||||
local runner_name log_name done_name done_status launcher_state
|
||||
local poll_rc state_rc log_rc start_seconds poll_deadline startup_checked
|
||||
runner_name="openclaw-gateway-restart-$RANDOM-$RANDOM.ps1"
|
||||
log_name="openclaw-gateway-restart-$RANDOM-$RANDOM.log"
|
||||
done_name="openclaw-gateway-restart-$RANDOM-$RANDOM.done"
|
||||
start_seconds="$SECONDS"
|
||||
poll_deadline=$((SECONDS + TIMEOUT_GATEWAY_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
|
||||
@'
|
||||
\$ErrorActionPreference = 'Stop'
|
||||
\$PSNativeCommandUseErrorActionPreference = \$false
|
||||
\$log = Join-Path \$env:TEMP '$log_name'
|
||||
\$done = Join-Path \$env:TEMP '$done_name'
|
||||
try {
|
||||
\$openclaw = Join-Path \$env:APPDATA 'npm\openclaw.cmd'
|
||||
& \$openclaw gateway restart *>&1 | Tee-Object -FilePath \$log -Append | Out-Null
|
||||
Set-Content -Path \$done -Value ([string]\$LASTEXITCODE)
|
||||
} catch {
|
||||
if (Test-Path \$log) {
|
||||
Add-Content -Path \$log -Value (\$_ | Out-String)
|
||||
} else {
|
||||
(\$_ | Out-String) | Set-Content -Path \$log
|
||||
}
|
||||
Set-Content -Path \$done -Value '1'
|
||||
}
|
||||
'@ | Set-Content -Path \$runner
|
||||
Start-Process powershell.exe -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', \$runner) -WindowStyle Hidden | Out-Null
|
||||
EOF
|
||||
)"
|
||||
|
||||
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 gateway restart helper poll failed; retrying"
|
||||
if (( SECONDS >= poll_deadline )); then
|
||||
warn "windows gateway restart helper timed out while polling done file"
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
continue
|
||||
fi
|
||||
if [[ -n "$done_status" ]]; then
|
||||
set +e
|
||||
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 ]]; then
|
||||
warn "windows gateway restart helper log drain failed after completion"
|
||||
fi
|
||||
[[ "$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 gateway restart helper failed to materialize guest files"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if (( SECONDS >= poll_deadline )); then
|
||||
set +e
|
||||
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 ]]; then
|
||||
warn "windows gateway restart helper log drain failed after timeout"
|
||||
fi
|
||||
warn "windows gateway restart helper timed out waiting for done file"
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
}
|
||||
|
||||
show_gateway_status_compat() {
|
||||
if guest_run_openclaw "" "" gateway status --help | grep -Fq -- "--require-rpc"; then
|
||||
guest_run_openclaw "" "" gateway status --deep --require-rpc
|
||||
|
|
@ -934,7 +1028,8 @@ show_gateway_status_compat() {
|
|||
}
|
||||
|
||||
verify_turn() {
|
||||
guest_run_openclaw "" "" agent --agent main --message "Reply with exact ASCII text OK only." --json
|
||||
guest_run_openclaw "OPENAI_API_KEY" "$OPENAI_API_KEY_VALUE" \
|
||||
agent --agent main --message "Reply with exact ASCII text OK only." --json
|
||||
}
|
||||
|
||||
capture_latest_ref_failure() {
|
||||
|
|
@ -990,6 +1085,7 @@ run_upgrade_lane() {
|
|||
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.gateway-restart" "$TIMEOUT_GATEWAY_S" restart_gateway || return $?
|
||||
phase_run "upgrade.onboard-ref" "$TIMEOUT_ONBOARD_S" run_ref_onboard || return $?
|
||||
phase_run "upgrade.gateway-status" "$TIMEOUT_GATEWAY_S" verify_gateway || return $?
|
||||
UPGRADE_GATEWAY_STATUS="pass"
|
||||
|
|
|
|||
|
|
@ -55,11 +55,12 @@ const TAR_GZ_TRAVERSAL_BUFFER = Buffer.from(
|
|||
|
||||
function buildEntry(name: string): SkillEntry {
|
||||
const skillDir = path.join(workspaceDir, "skills", name);
|
||||
const filePath = path.join(skillDir, "SKILL.md");
|
||||
return {
|
||||
skill: createFixtureSkill({
|
||||
name,
|
||||
description: `${name} test skill`,
|
||||
filePath: path.join(skillDir, "SKILL.md"),
|
||||
filePath,
|
||||
baseDir: skillDir,
|
||||
source: "openclaw-workspace",
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -30,12 +30,14 @@ function makeEntry(params: {
|
|||
label?: string;
|
||||
}>;
|
||||
}): SkillEntry {
|
||||
const filePath = `/tmp/${params.name}/SKILL.md`;
|
||||
const baseDir = `/tmp/${params.name}`;
|
||||
return {
|
||||
skill: createFixtureSkill({
|
||||
name: params.name,
|
||||
description: `desc:${params.name}`,
|
||||
filePath: `/tmp/${params.name}/SKILL.md`,
|
||||
baseDir: `/tmp/${params.name}`,
|
||||
filePath,
|
||||
baseDir,
|
||||
source: params.source ?? "openclaw-workspace",
|
||||
}),
|
||||
frontmatter: {},
|
||||
|
|
|
|||
|
|
@ -32,12 +32,13 @@ describe("skills-cli (e2e)", () => {
|
|||
|
||||
function createEntries(): SkillEntry[] {
|
||||
const baseDir = path.join(tempWorkspaceDir, "peekaboo");
|
||||
const filePath = path.join(baseDir, "SKILL.md");
|
||||
return [
|
||||
{
|
||||
skill: createFixtureSkill({
|
||||
name: "peekaboo",
|
||||
description: "Capture UI screenshots",
|
||||
filePath: path.join(baseDir, "SKILL.md"),
|
||||
filePath,
|
||||
baseDir,
|
||||
source: "openclaw-bundled",
|
||||
}),
|
||||
|
|
|
|||
Loading…
Reference in New Issue