From 17a1993f1395aaf59d415cc9cde5cafde4a76a9f Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 5 Jul 2026 12:36:07 +0200 Subject: [PATCH] fix(e2e): stop waiting for skipped skills prompt --- scripts/e2e/lib/onboard/scenario.sh | 52 ++++++++++++++++++++---- test/scripts/e2e-shell-tempfiles.test.ts | 39 +++++++++++++++++- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/scripts/e2e/lib/onboard/scenario.sh b/scripts/e2e/lib/onboard/scenario.sh index bb07ced6085c..8ca64f4274fd 100644 --- a/scripts/e2e/lib/onboard/scenario.sh +++ b/scripts/e2e/lib/onboard/scenario.sh @@ -43,6 +43,17 @@ send() { printf "%b" "$payload" >&3 2>/dev/null || true } +log_contains() { + local needle="$1" + if [ -z "${WIZARD_LOG_PATH:-}" ] || [ ! -f "$WIZARD_LOG_PATH" ]; then + return 1 + fi + if grep -a -F -q "$needle" "$WIZARD_LOG_PATH"; then + return 0 + fi + node scripts/e2e/lib/onboard/log-contains.mjs "$WIZARD_LOG_PATH" "$needle" +} + wait_for_log() { local needle="$1" local timeout_s="${2:-45}" @@ -50,13 +61,8 @@ wait_for_log() { local start_s start_s="$(date +%s)" while true; do - if [ -n "${WIZARD_LOG_PATH:-}" ] && [ -f "$WIZARD_LOG_PATH" ]; then - if grep -a -F -q "$needle" "$WIZARD_LOG_PATH"; then - return 0 - fi - if node scripts/e2e/lib/onboard/log-contains.mjs "$WIZARD_LOG_PATH" "$needle"; then - return 0 - fi + if log_contains "$needle"; then + return 0 fi if [ $(($(date +%s) - start_s)) -ge "$timeout_s" ]; then if [ "$quiet_on_timeout" = "true" ]; then @@ -72,6 +78,28 @@ wait_for_log() { done } +wait_for_skills_prompt_or_ready() { + local timeout_s="${1:-45}" + local start_s + start_s="$(date +%s)" + while true; do + if log_contains "Configure skills now?"; then + return 0 + fi + if log_contains "All skills ready"; then + return 2 + fi + if [ $(($(date +%s) - start_s)) -ge "$timeout_s" ]; then + echo "Timeout waiting for skills prompt or ready state" + if [ -n "${WIZARD_LOG_PATH:-}" ] && [ -f "$WIZARD_LOG_PATH" ]; then + tail -n 140 "$WIZARD_LOG_PATH" || true + fi + return 1 + fi + sleep 0.2 + done +} + start_gateway() { GATEWAY_PID="$(openclaw_e2e_start_gateway "$OPENCLAW_ENTRY" 18789 "$GATEWAY_LOG_PATH")" } @@ -202,8 +230,14 @@ send_channels_flow() { send_skills_flow() { # configure --section skills still runs the configure wizard, without the # gateway run-mode prompt used by the full wizard. - wait_for_log "Configure skills now?" 120 - send $'n\r' 0.8 + if wait_for_skills_prompt_or_ready 120; then + send $'n\r' 0.8 + else + local status="$?" + if [ "$status" -ne 2 ]; then + return "$status" + fi + fi send "" 2.0 } diff --git a/test/scripts/e2e-shell-tempfiles.test.ts b/test/scripts/e2e-shell-tempfiles.test.ts index 6ae4e816733b..c8b232abdb0e 100644 --- a/test/scripts/e2e-shell-tempfiles.test.ts +++ b/test/scripts/e2e-shell-tempfiles.test.ts @@ -3,7 +3,10 @@ import { spawnSync } from "node:child_process"; import { mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; -import { describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it } from "vitest"; +import { useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js"; + +const tempDirs = useAutoCleanupTempDirTracker(afterEach); async function listShellScripts(dir: string): Promise { const entries = await readdir(dir, { withFileTypes: true }); @@ -93,6 +96,40 @@ run_wizard_cmd failing-wizard fake-state "node fake-wizard" send_noop false } }); + it("does not wait for a skills prompt after the ready state renders", async () => { + const tempRoot = tempDirs.make("openclaw-onboard-skills-ready-"); + const fixturePath = path.join(tempRoot, "skills-ready.sh"); + const sentPath = path.join(tempRoot, "sent.txt"); + const wizardLogPath = path.join(tempRoot, "skills.log"); + await writeFile( + fixturePath, + `#!/usr/bin/env bash +set -euo pipefail + +export OPENCLAW_ONBOARD_SCENARIO_SOURCE_ONLY=1 +export OPENCLAW_ONBOARD_E2E_TMPDIR=${JSON.stringify(tempRoot)} +OPENCLAW_ENTRY=node +source scripts/e2e/lib/onboard/scenario.sh + +sleep() { :; } +WIZARD_LOG_PATH=${JSON.stringify(wizardLogPath)} +printf 'Skills status\\nAll skills ready\\n' >"$WIZARD_LOG_PATH" +exec 3>${JSON.stringify(sentPath)} +send_skills_flow +exec 3>&- +test ! -s ${JSON.stringify(sentPath)} +`, + ); + + const result = spawnSync("bash", [fixturePath], { + cwd: process.cwd(), + encoding: "utf8", + }); + + expect(result.status, `${result.stdout}\n${result.stderr}`).toBe(0); + expect(`${result.stdout}\n${result.stderr}`).not.toContain("Timeout waiting"); + }); + it("checks local onboarding logs for systemd noise", async () => { const contents = await readFile("scripts/e2e/lib/onboard/scenario.sh", "utf8");