Files
llm-intelligence/scripts/verify_lighthouse.sh

93 lines
2.7 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
FRONTEND_DIR="$PROJECT_ROOT/frontend"
LIGHTHOUSE_PORT="${LIGHTHOUSE_PORT:-4173}"
LIGHTHOUSE_SCORE_THRESHOLD="${LIGHTHOUSE_SCORE_THRESHOLD:-80}"
LIGHTHOUSE_FCP_THRESHOLD_MS="${LIGHTHOUSE_FCP_THRESHOLD_MS:-2000}"
LIGHTHOUSE_URL="http://127.0.0.1:${LIGHTHOUSE_PORT}"
LIGHTHOUSE_JSON="${TMPDIR:-/tmp}/llm_lighthouse_report.json"
PREVIEW_LOG="${TMPDIR:-/tmp}/llm_lighthouse_preview.log"
PREVIEW_PID=""
CHROME_BIN=""
cleanup() {
if [[ -n "${PREVIEW_PID:-}" ]] && kill -0 "$PREVIEW_PID" >/dev/null 2>&1; then
kill "$PREVIEW_PID" >/dev/null 2>&1 || true
wait "$PREVIEW_PID" >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT
for candidate in /usr/bin/google-chrome-stable /usr/bin/google-chrome /snap/bin/chromium /usr/bin/chromium /usr/bin/chromium-browser; do
if [[ -x "$candidate" ]]; then
CHROME_BIN="$candidate"
break
fi
done
if [[ -z "$CHROME_BIN" ]]; then
echo "LIGHTHOUSE_ERROR=chrome-not-found"
exit 1
fi
cd "$FRONTEND_DIR"
npm run build >/tmp/llm_lighthouse_build.out 2>/tmp/llm_lighthouse_build.err
npm exec vite preview -- --host 127.0.0.1 --port "$LIGHTHOUSE_PORT" >"$PREVIEW_LOG" 2>&1 &
PREVIEW_PID=$!
for _ in $(seq 1 30); do
if curl -fsS "$LIGHTHOUSE_URL" >/dev/null 2>&1; then
break
fi
sleep 0.5
done
if ! curl -fsS "$LIGHTHOUSE_URL" >/dev/null 2>&1; then
echo "LIGHTHOUSE_ERROR=preview-not-ready"
exit 1
fi
npx lighthouse "$LIGHTHOUSE_URL" \
--chrome-path="$CHROME_BIN" \
--only-categories=performance \
--preset=desktop \
--output=json \
--output-path="$LIGHTHOUSE_JSON" \
--quiet \
--chrome-flags="--headless=new --no-sandbox --disable-dev-shm-usage" \
>/tmp/llm_lighthouse_stdout.out 2>/tmp/llm_lighthouse_stderr.err
read -r score fcp speed_index lcp <<EOF
$(node -e '
const fs = require("fs");
const report = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
const perf = Math.round((report.categories.performance.score || 0) * 100);
const fcp = Math.round(report.audits["first-contentful-paint"]?.numericValue || 0);
const speedIndex = Math.round(report.audits["speed-index"]?.numericValue || 0);
const lcp = Math.round(report.audits["largest-contentful-paint"]?.numericValue || 0);
console.log(`${perf} ${fcp} ${speedIndex} ${lcp}`);
' "$LIGHTHOUSE_JSON")
EOF
echo "LIGHTHOUSE_SCORE=${score}"
echo "LIGHTHOUSE_FCP_MS=${fcp}"
echo "LIGHTHOUSE_SPEED_INDEX_MS=${speed_index}"
echo "LIGHTHOUSE_LCP_MS=${lcp}"
if (( score < LIGHTHOUSE_SCORE_THRESHOLD )); then
echo "LIGHTHOUSE_ERROR=score-below-threshold"
exit 1
fi
if (( fcp >= LIGHTHOUSE_FCP_THRESHOLD_MS )); then
echo "LIGHTHOUSE_ERROR=fcp-above-threshold"
exit 1
fi