fix(cua): stronger connect phase + fallback pre-create for external server

connect phase: now verifies the connection appears in the list after saving,
not just that the form was dismissed. Prevents false PASS when the LLM
declares connect done before the entry is actually visible.

_precreate_test_session: when external URL (Tailscale) times out from the
CI runner, fall back to localhost:4096 (the runner-local opencode serve).
This ensures the named-session assertion stays active in standard CI runs
while also working when dispatched against a live external server.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Dennis V
2026-06-23 09:11:20 +00:00
parent 1dafdcbc65
commit 6198e4e165

View File

@@ -625,7 +625,14 @@ def _precreate_test_session(opencode_url: str, title: str = "cua-smoke-sessions-
# When opencode_url uses the Android emulator's host-route (10.0.2.2),
# translate it to localhost for this pre-create call — 10.0.2.2 is
# only reachable from *inside* the emulator, not from the host/CI runner.
api_base = opencode_url.replace("10.0.2.2", "127.0.0.1")
# When opencode_url uses an external address (Tailscale, etc.) that the
# CI runner can't reach, fall back to localhost:4096 (the runner-local server).
candidates = [opencode_url.replace("10.0.2.2", "127.0.0.1")]
# If the URL isn't already localhost, also try 127.0.0.1:4096 as fallback
if "127.0.0.1" not in candidates[0] and "localhost" not in candidates[0]:
candidates.append("http://127.0.0.1:4096")
for api_base in candidates:
url = f"{api_base.rstrip('/')}/session"
data = json.dumps({"title": title}).encode()
req = urllib.request.Request(
@@ -633,14 +640,15 @@ def _precreate_test_session(opencode_url: str, title: str = "cua-smoke-sessions-
headers={"Content-Type": "application/json"},
)
try:
with urllib.request.urlopen(req, timeout=10) as resp:
with urllib.request.urlopen(req, timeout=5) as resp:
body = json.loads(resp.read())
session_id = body.get("id", "unknown")
print(f" [pre-create] session created via API ({api_base}): id={session_id!r}, title={title!r}")
return title
except Exception as exc:
print(f" [pre-create] WARNING: could not pre-create session at {api_base}: {exc}")
print(f" [pre-create] session_list phase will skip the 'must show sessions' assertion")
print(f" [pre-create] {api_base} unreachable: {exc}")
print(f" [pre-create] WARNING: all candidates failed — session_list phase will skip named-session assertion")
return None
@@ -703,12 +711,15 @@ def run_onboarding_showcase(
goal=(
f"You are on the OpenCode mobile app. "
"The screen shows either a connection screen (first launch) or an empty connections list. "
"Your goal: add a new connection to the opencode server. "
"Look for an 'Add Connection', '+', or 'New Connection' button and tap it. "
f"In the URL / Host field type '{opencode_url}'. "
"Leave username and password blank. "
"Tap 'Save', 'Connect', or 'Done' to save the connection. "
"Report done when you can see the connection has been saved or the app navigated away from the add-connection form."
"Your goal: add a new connection to the opencode server and verify it is saved. "
"Step 1: Look for an 'Add Connection', '+', or 'New Connection' button and tap it. "
f"Step 2: In the URL / Host field type '{opencode_url}'. "
"Step 3: Leave username and password blank. "
"Step 4: Tap 'Save', 'Connect', or 'Done' to save the connection. "
"Step 5: IMPORTANT — after saving, you must see the connection appear in the connections list "
f"(showing the URL '{opencode_url}' or a name derived from it). "
"If you are back on the connections list and can see the saved connection entry, report done. "
"If the form is still showing or the list is empty, the save did not work — try again."
),
max_steps=max_steps_per_phase,
)