Skip to content

Commit 491bd0e

Browse files
iangmaiaCopilot
andauthored
Add AI E2E test site preflight (#25615)
* Add AI E2E test site preflight * Fix mktemp temp dir portability in AI E2E preflight script * Require HTTPS for AI E2E test site * Restrict AI E2E preflight redirects to HTTPS --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent f64ac0b commit 491bd0e

1 file changed

Lines changed: 122 additions & 3 deletions

File tree

.buildkite/commands/run-ai-e2e-tests.sh

Lines changed: 122 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
#
44
# This script manages the full lifecycle:
55
# 1. Check for "Testing" label on PR (Buildkite only, skips if missing)
6-
# 2. Download build artifacts and install app (Buildkite only)
7-
# 3. Install the simulator-llm-pilot gem from GitHub
8-
# 4. Run tests (gem handles simulator, WDA, agent loop, and results)
6+
# 2. Preflight the configured WordPress test site
7+
# 3. Download build artifacts and install app (Buildkite only)
8+
# 4. Install the simulator-llm-pilot gem from GitHub
9+
# 5. Run tests (gem handles simulator, WDA, agent loop, and results)
910
#
1011
# The gem provides a sandboxed agent that drives the simulator through a
1112
# fixed set of tools (tap, swipe, type, REST API, etc.) — no arbitrary
@@ -39,6 +40,119 @@ normalize_site_url() {
3940
fi
4041
}
4142

43+
validate_https_site_url() {
44+
local site_url="$1"
45+
if [[ "$site_url" == https://* ]]; then
46+
return 0
47+
fi
48+
49+
echo "Error: SIMULATOR_LLM_PILOT_SITE_URL must use https://." >&2
50+
echo "The AI E2E tests send an application password via HTTP Basic Auth for REST API setup and verification." >&2
51+
echo "Configured URL: ${site_url}" >&2
52+
return 1
53+
}
54+
55+
site_url_with_path() {
56+
local site_url="${1%/}"
57+
local path="$2"
58+
printf '%s%s' "$site_url" "$path"
59+
}
60+
61+
preflight_current_user_auth() {
62+
local body_file="$1"
63+
grep -q '"id"[[:space:]]*:' "$body_file"
64+
}
65+
66+
preflight_rest_api_root() {
67+
local body_file="$1"
68+
grep -q '"namespaces"[[:space:]]*:' "$body_file" && grep -q '"routes"[[:space:]]*:' "$body_file"
69+
}
70+
71+
preflight_endpoint() {
72+
local label="$1"
73+
local url="$2"
74+
local body_check="$3"
75+
local auth_mode="${4:-anonymous}"
76+
local body_file
77+
local curl_args
78+
local curl_output
79+
local http_status
80+
local effective_url
81+
local redirect_count
82+
83+
body_file="$(mktemp "${PREFLIGHT_TMP_DIR}/body.XXXXXX")"
84+
85+
curl_args=(
86+
--silent
87+
--show-error
88+
--location
89+
--max-redirs 3
90+
--connect-timeout 10
91+
--max-time 20
92+
--proto '=https'
93+
--proto-redir '=https'
94+
--output "$body_file"
95+
--write-out "%{http_code} %{url_effective} %{num_redirects}"
96+
)
97+
98+
if [[ "$auth_mode" == "authenticated" ]]; then
99+
curl_args+=(--user "${SIMULATOR_LLM_PILOT_USERNAME}:${SIMULATOR_LLM_PILOT_APP_PASSWORD}")
100+
fi
101+
102+
curl_args+=("$url")
103+
104+
if ! curl_output="$(curl "${curl_args[@]}")"; then
105+
echo "Error: unable to reach ${label} at ${url}" >&2
106+
return 1
107+
fi
108+
109+
read -r http_status effective_url redirect_count <<< "$curl_output"
110+
111+
if [[ "$effective_url" == *"wordpress.com/typo"* ]]; then
112+
echo "Error: ${label} redirected to WordPress.com typo handling." >&2
113+
echo "Configured URL: ${url}" >&2
114+
echo "Final URL: ${effective_url}" >&2
115+
echo "The AI E2E test site is likely missing or no longer mapped." >&2
116+
return 1
117+
fi
118+
119+
if [[ "$http_status" != 2* ]]; then
120+
echo "Error: ${label} returned HTTP ${http_status}." >&2
121+
echo "URL: ${url}" >&2
122+
if [[ "$redirect_count" != "0" ]]; then
123+
echo "Final URL after ${redirect_count} redirect(s): ${effective_url}" >&2
124+
fi
125+
if [[ "$auth_mode" == "authenticated" && "$http_status" == "401" ]]; then
126+
echo "Check SIMULATOR_LLM_PILOT_USERNAME and SIMULATOR_LLM_PILOT_APP_PASSWORD." >&2
127+
fi
128+
return 1
129+
fi
130+
131+
if ! "$body_check" "$body_file"; then
132+
echo "Error: ${label} returned HTTP ${http_status}, but the response does not look like the expected WordPress REST API response." >&2
133+
echo "URL: ${url}" >&2
134+
if [[ "$redirect_count" != "0" ]]; then
135+
echo "Final URL after ${redirect_count} redirect(s): ${effective_url}" >&2
136+
fi
137+
return 1
138+
fi
139+
140+
echo "OK: ${label} returned HTTP ${http_status}"
141+
}
142+
143+
preflight_test_site() {
144+
local api_root_url
145+
local current_user_url
146+
147+
echo "--- Preflighting AI E2E Test Site"
148+
149+
api_root_url="$(site_url_with_path "$SIMULATOR_LLM_PILOT_SITE_URL" "/wp-json/")"
150+
current_user_url="$(site_url_with_path "$SIMULATOR_LLM_PILOT_SITE_URL" "/wp-json/wp/v2/users/me")"
151+
152+
preflight_endpoint "REST API root" "$api_root_url" preflight_rest_api_root
153+
preflight_endpoint "authenticated current user endpoint" "$current_user_url" preflight_current_user_auth "authenticated"
154+
}
155+
42156
# ── Label gate (Buildkite only) ─────────────────────────────────────
43157
if [[ -n "${BUILDKITE_PULL_REQUEST_LABELS:-}" ]]; then
44158
echo "--- Checking for 'Testing' label"
@@ -57,6 +171,11 @@ fi
57171
: "${SIMULATOR_LLM_PILOT_USERNAME:?Set SIMULATOR_LLM_PILOT_USERNAME}"
58172
: "${SIMULATOR_LLM_PILOT_APP_PASSWORD:?Set SIMULATOR_LLM_PILOT_APP_PASSWORD}"
59173
export SIMULATOR_LLM_PILOT_SITE_URL="$(normalize_site_url "$SIMULATOR_LLM_PILOT_SITE_URL")"
174+
validate_https_site_url "$SIMULATOR_LLM_PILOT_SITE_URL"
175+
176+
PREFLIGHT_TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/preflight.XXXXXX" 2>/dev/null || mktemp -d -t preflight)"
177+
trap 'rm -rf "$PREFLIGHT_TMP_DIR"' EXIT
178+
preflight_test_site
60179

61180
# ── Defaults ─────────────────────────────────────────────────────────
62181
APP="${APP:-jetpack}"

0 commit comments

Comments
 (0)