Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 2 additions & 34 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,40 +66,8 @@ jobs:

- name: Smoke test dev server
shell: bash
env:
NITRO_DEV_RUNNER: ${{ matrix.os == 'windows-latest' && 'self' || '' }}
run: |
./packages/chronicle/bin/chronicle.js dev --config examples/basic/chronicle.yaml --port 3001 &
DEV_PID=$!
for i in $(seq 1 30); do
if curl -sf http://localhost:3001/api/health > /dev/null 2>&1; then
echo "Dev server ready"
break
fi
sleep 2
done
curl -sf http://localhost:3001/api/health | grep -q '"ok"'
echo "Dev server health check passed"
curl -sfL http://localhost:3001/ | grep -q 'getting-started'
echo "Dev server content check passed"
kill $DEV_PID 2>/dev/null || true
run: ./scripts/smoke-test.sh dev 3001

- name: Smoke test start server
shell: bash
run: |
./packages/chronicle/bin/chronicle.js start --config examples/basic/chronicle.yaml --port 3002 &
START_PID=$!
for i in $(seq 1 30); do
if curl -sf http://localhost:3002/api/health > /dev/null 2>&1; then
echo "Start server ready"
break
fi
sleep 2
done
curl -sf http://localhost:3002/api/health | grep -q '"ok"'
echo "Start server health check passed"
curl -sfL http://localhost:3002/ | grep -q 'getting-started'
echo "Start server content check passed"
curl -sf "http://localhost:3002/api/page?slug=docs,getting-started" | grep -q '"title"'
echo "Page API check passed"
kill $START_PID 2>/dev/null || true
run: ./scripts/smoke-test.sh start 3002
99 changes: 99 additions & 0 deletions scripts/smoke-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Smoke test a chronicle server against examples/basic.
# Usage: scripts/smoke-test.sh <dev|start> <port>
set -euo pipefail

MODE="${1:?usage: smoke-test.sh <dev|start> <port>}"
PORT="${2:?usage: smoke-test.sh <dev|start> <port>}"
BASE="http://localhost:${PORT}"
LOG_FILE="smoke-${MODE}.log"

./packages/chronicle/bin/chronicle.js "$MODE" --config examples/basic/chronicle.yaml --port "$PORT" >"$LOG_FILE" 2>&1 &
SERVER_PID=$!

cleanup() {
# Git Bash `kill` doesn't reach grandchild node processes on Windows
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
taskkill //F //T //PID "$SERVER_PID" >/dev/null 2>&1 || true
else
kill "$SERVER_PID" 2>/dev/null || true
fi
}
trap cleanup EXIT

fail() {
echo "FAIL: $1"
echo "--- server log (${LOG_FILE}) ---"
cat "$LOG_FILE"
exit 1
}

# Wall-clock deadline; SECONDS counts from script start, which includes server spawn
HEALTH_BUDGET="${HEALTH_BUDGET:-120}"
healthy=0
while (( SECONDS < HEALTH_BUDGET )); do
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
fail "${MODE} server exited before becoming healthy"
fi
if curl -sf --max-time 5 "${BASE}/api/health" | grep -q '"ok"'; then
healthy=1
break
fi
sleep 2
done
if [[ "$healthy" -ne 1 ]]; then
fail "${MODE} server not healthy after ${HEALTH_BUDGET}s"
fi
echo "${MODE} server health check passed"

# Load-time budgets (seconds); first load includes SSR compile in dev mode
FIRST_LOAD_BUDGET="${FIRST_LOAD_BUDGET:-60}"
WARM_LOAD_BUDGET="${WARM_LOAD_BUDGET:-10}"
BODY_FILE="smoke-${MODE}-page.html"

first_time=$(curl -sfL -o "$BODY_FILE" -w '%{time_total}' --max-time "$FIRST_LOAD_BUDGET" "${BASE}/") \
|| fail "first page load failed or exceeded ${FIRST_LOAD_BUDGET}s budget"
if ! grep -q 'getting-started' "$BODY_FILE"; then
fail "homepage does not contain expected content"
fi
echo "${MODE} server content check passed (first load ${first_time}s, budget ${FIRST_LOAD_BUDGET}s)"

warm_time=$(curl -sfL -o /dev/null -w '%{time_total}' --max-time "$WARM_LOAD_BUDGET" "${BASE}/") \
|| fail "warm page load failed or exceeded ${WARM_LOAD_BUDGET}s budget"
echo "${MODE} server warm load check passed (${warm_time}s, budget ${WARM_LOAD_BUDGET}s)"

if ! curl -sf --max-time 30 "${BASE}/api/page?slug=docs,getting-started" | grep -q '"title"'; then
fail "page API did not return page metadata"
fi
echo "${MODE} server page API check passed"

# Crawl pages from the sitemap; in dev mode each request exercises SSR compile
CRAWL_LIMIT="${CRAWL_LIMIT:-15}"
CRAWL_BUDGET="${CRAWL_BUDGET:-300}"

# `|| true`: an empty sitemap makes grep exit 1, which must reach the
# explicit fail below instead of killing the script under pipefail
paths=$(curl -sf --max-time 30 "${BASE}/sitemap.xml" \
| grep -o '<loc>[^<]*</loc>' \
| sed -E -e 's|</?loc>||g' -e 's|^https?://[^/]*||' -e 's|^$|/|' \
| awk -v n="$CRAWL_LIMIT" 'NR <= n' || true)
if [[ -z "$paths" ]]; then
fail "sitemap.xml returned no URLs"
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.

crawled=0
crawl_start=$SECONDS
while IFS= read -r page_path; do
if (( SECONDS - crawl_start > CRAWL_BUDGET )); then
fail "crawl exceeded ${CRAWL_BUDGET}s budget after ${crawled} pages"
fi
status=$(curl -sL -o "$BODY_FILE" -w '%{http_code}' --max-time 30 "${BASE}${page_path}") || status=000
if [[ "$status" != "200" ]]; then
fail "GET ${page_path} returned HTTP ${status}"
fi
if ! grep -q '</html>' "$BODY_FILE"; then
fail "GET ${page_path} returned truncated or incomplete HTML"
fi
crawled=$((crawled + 1))
done <<<"$paths"
echo "${MODE} server crawl passed (${crawled} pages)"
Loading