Skip to content

Commit dcca7e4

Browse files
ci(examples): assert exact status/body instead of liveness-only check (#755)
* ci(examples): assert exact status/body instead of liveness-only check The verify step in test-image/test-zip/test-stream treated any 2xx-4xx response as success, so a broken route (404) or an app that booted but served the wrong/empty content still passed. Add .github/scripts/verify-http.sh which waits for an endpoint to return an exact status code and (optionally) a known body substring, and convert each job's matrix to objects carrying {path, expect_status, expect_body} so every example asserts its real response. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(examples): honor PORT in fasthtml-response-streaming --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c7f2899 commit dcca7e4

6 files changed

Lines changed: 187 additions & 136 deletions

File tree

.github/scripts/verify-http.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Verify that an example's HTTP endpoint serves the expected response.
4+
#
5+
# Unlike a plain liveness check (any 2xx-4xx == "OK"), this asserts that a
6+
# specific route returns an exact status code and, optionally, that the body
7+
# contains a known substring. This catches broken routing and apps that boot
8+
# but serve the wrong (or empty) content.
9+
#
10+
# Usage:
11+
# verify-http.sh <base_url> <path> <expect_status> [expect_body]
12+
#
13+
# base_url e.g. http://127.0.0.1:3000
14+
# path request path, e.g. / or /healthz
15+
# expect_status comma-separated acceptable status codes, e.g. "200" or "200,307"
16+
# expect_body optional substring that must appear in the response body
17+
#
18+
# Waits up to 90s (wall-clock) for the endpoint to satisfy BOTH conditions
19+
# (the app may still be warming up), then exits 0 on success or 1 with
20+
# diagnostics. Uses a wall-clock deadline plus a short per-request timeout
21+
# (curl -m 5) so a hanging endpoint can't multiply the wait window.
22+
23+
set -uo pipefail
24+
25+
BASE_URL="${1:?base_url required}"
26+
REQ_PATH="${2:-/}"
27+
EXPECT_STATUS="${3:-200}"
28+
EXPECT_BODY="${4:-}"
29+
30+
URL="${BASE_URL%/}${REQ_PATH}"
31+
IFS=',' read -ra ACCEPT <<< "$EXPECT_STATUS"
32+
33+
status_ok() {
34+
local s="$1"
35+
for code in "${ACCEPT[@]}"; do
36+
[ "$s" = "$code" ] && return 0
37+
done
38+
return 1
39+
}
40+
41+
echo "Verifying ${URL} (expect status ${EXPECT_STATUS}${EXPECT_BODY:+, body contains \"${EXPECT_BODY}\"})"
42+
43+
last_status=""
44+
last_body=""
45+
START=$SECONDS
46+
DEADLINE=$((START + 90))
47+
while [ $SECONDS -lt $DEADLINE ]; do
48+
resp="$(curl -s -m 5 -w $'\n%{http_code}' "$URL" 2>/dev/null || true)"
49+
last_status="${resp##*$'\n'}"
50+
last_body="${resp%$'\n'*}"
51+
if status_ok "$last_status"; then
52+
if [ -z "$EXPECT_BODY" ] || grep -qF -- "$EXPECT_BODY" <<< "$last_body"; then
53+
echo "OK after $((SECONDS - START))s: status ${last_status}${EXPECT_BODY:+, body contains \"${EXPECT_BODY}\"}"
54+
exit 0
55+
fi
56+
fi
57+
sleep 1
58+
done
59+
60+
echo "FAIL: expectation not met within 90s (elapsed $((SECONDS - START))s)"
61+
echo " last status: ${last_status:-<none>} (expected ${EXPECT_STATUS})"
62+
[ -n "$EXPECT_BODY" ] && echo " expected body substring: ${EXPECT_BODY}"
63+
echo "--- last response body (first 30 lines) ---"
64+
printf '%s\n' "$last_body" | head -30
65+
exit 1

0 commit comments

Comments
 (0)