mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-03-13 22:12:54 +03:00
* feat: add E2E testing infrastructure with fake GitHub, Playwright, and CI workflow - Add fake GitHub API server (tests/e2e/fake-github-server.ts) with management API for seeding test data - Add Playwright E2E test suite covering full mirror workflow: service health checks, user registration, config, sync, verify - Add Docker Compose for E2E Gitea instance - Add orchestrator script (run-e2e.sh) with cleanup - Add GitHub Actions workflow (e2e-tests.yml) with Gitea service container - Make GITHUB_API_URL configurable via env var for testing - Add npm scripts: test:e2e, test:e2e:ci, test:e2e:keep, test:e2e:cleanup * feat: add real git repos + backup config testing to E2E suite - Create programmatic test git repos (create-test-repos.ts) with real commits, branches (main, develop, feature/*), and tags (v1.0.0, v1.1.0) - Add git-server container to docker-compose serving bare repos via dumb HTTP protocol so Gitea can actually clone them - Update fake GitHub server to emit reachable clone_url fields pointing to the git-server container (configurable via GIT_SERVER_URL env var) - Add management endpoint POST /___mgmt/set-clone-url for runtime config - Update E2E spec with real mirroring verification: * Verify repos appear in Gitea with actual content * Check branches, tags, commits, file content * Verify 4/4 repos mirrored successfully - Add backup configuration test suite: * Enable/disable backupBeforeSync config * Toggle blockSyncOnBackupFailure * Trigger re-sync with backup enabled and verify activities * Verify config persistence across changes - Update CI workflow to use docker compose (not service containers) matching the local run-e2e.sh approach - Update cleanup.sh for git-repos directory and git-server port - All 22 tests passing with real git content verification * refactor: split E2E tests into focused files + add force-push tests Split the monolithic e2e.spec.ts (1335 lines) into 5 focused spec files and a shared helpers module: helpers.ts — constants, GiteaAPI, auth, saveConfig, utilities 01-health.spec.ts — service health checks (4 tests) 02-mirror-workflow.spec.ts — full first-mirror journey (8 tests) 03-backup.spec.ts — backup config toggling (6 tests) 04-force-push.spec.ts — force-push simulation & backup verification (9 tests) 05-sync-verification.spec.ts — dynamic repos, content integrity, reset (5 tests) The force-push tests are the critical addition: F0: Record original state (commit SHAs, file content) F1: Rewrite source repo history (simulate force-push) F2: Sync to Gitea WITHOUT backup F3: Verify data loss — LICENSE file gone, README overwritten F4: Restore source, re-mirror to clean state F5: Enable backup, force-push again, sync through app F6: Verify Gitea reflects the force-push F7: Verify backup system was invoked (snapshot activities logged) F8: Restore source repo for subsequent tests Also added to helpers.ts: - GiteaAPI.getBranch(), .getCommit(), .triggerMirrorSync() - getRepositoryIds(), triggerMirrorJobs(), triggerSyncRepo() All 32 tests passing. * Try to fix actions * Try to fix the other action * Add debug info to check why e2e action is failing * More debug info * Even more debug info * E2E fix attempt #1 * E2E fix attempt #2 * more debug again * E2E fix attempt #3 * E2E fix attempt #4 * Remove a bunch of debug info * Hopefully fix backup bug * Force backups to succeed
456 lines
19 KiB
Bash
Executable File
456 lines
19 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# ────────────────────────────────────────────────────────────────────────────────
|
||
# E2E Test Orchestrator
|
||
#
|
||
# Starts all required services, runs Playwright E2E tests, and tears down.
|
||
#
|
||
# Services managed:
|
||
# 1. Gitea instance (Docker/Podman on port 3333)
|
||
# 2. Fake GitHub API (Node.js on port 4580)
|
||
# 3. gitea-mirror app (Astro dev server on port 4321)
|
||
#
|
||
# Usage:
|
||
# ./tests/e2e/run-e2e.sh # full run (cleanup → start → test → teardown)
|
||
# ./tests/e2e/run-e2e.sh --no-build # skip the Astro build step
|
||
# ./tests/e2e/run-e2e.sh --keep # don't tear down services after tests
|
||
# ./tests/e2e/run-e2e.sh --ci # CI-friendly mode (stricter, no --keep)
|
||
#
|
||
# Environment variables:
|
||
# GITEA_PORT (default: 3333)
|
||
# FAKE_GITHUB_PORT (default: 4580)
|
||
# APP_PORT (default: 4321)
|
||
# SKIP_CLEANUP (default: false) set "true" to skip initial cleanup
|
||
# BUN_CMD (default: auto-detected bun or "npx --yes bun")
|
||
# ────────────────────────────────────────────────────────────────────────────────
|
||
set -euo pipefail
|
||
|
||
# ─── Resolve paths ────────────────────────────────────────────────────────────
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
COMPOSE_FILE="$SCRIPT_DIR/docker-compose.e2e.yml"
|
||
|
||
# ─── Configuration ────────────────────────────────────────────────────────────
|
||
GITEA_PORT="${GITEA_PORT:-3333}"
|
||
FAKE_GITHUB_PORT="${FAKE_GITHUB_PORT:-4580}"
|
||
APP_PORT="${APP_PORT:-4321}"
|
||
GIT_SERVER_PORT="${GIT_SERVER_PORT:-4590}"
|
||
|
||
GITEA_URL="http://localhost:${GITEA_PORT}"
|
||
FAKE_GITHUB_URL="http://localhost:${FAKE_GITHUB_PORT}"
|
||
APP_URL="http://localhost:${APP_PORT}"
|
||
GIT_SERVER_URL="http://localhost:${GIT_SERVER_PORT}"
|
||
# URL that Gitea (inside Docker) uses to reach the git-server container
|
||
GIT_SERVER_INTERNAL_URL="http://git-server"
|
||
|
||
NO_BUILD=false
|
||
KEEP_RUNNING=false
|
||
CI_MODE=false
|
||
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
--no-build) NO_BUILD=true ;;
|
||
--keep) KEEP_RUNNING=true ;;
|
||
--ci) CI_MODE=true ;;
|
||
--help|-h)
|
||
echo "Usage: $0 [--no-build] [--keep] [--ci]"
|
||
exit 0
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# ─── Detect tools ─────────────────────────────────────────────────────────────
|
||
|
||
# Container runtime
|
||
COMPOSE_CMD=""
|
||
CONTAINER_CMD=""
|
||
if command -v podman-compose &>/dev/null; then
|
||
COMPOSE_CMD="podman-compose"
|
||
CONTAINER_CMD="podman"
|
||
elif command -v docker-compose &>/dev/null; then
|
||
COMPOSE_CMD="docker-compose"
|
||
CONTAINER_CMD="docker"
|
||
elif command -v docker &>/dev/null && docker compose version &>/dev/null 2>&1; then
|
||
COMPOSE_CMD="docker compose"
|
||
CONTAINER_CMD="docker"
|
||
else
|
||
echo "ERROR: No container compose tool found. Install docker-compose or podman-compose."
|
||
exit 1
|
||
fi
|
||
|
||
# Bun or fallback
|
||
if command -v bun &>/dev/null; then
|
||
BUN_CMD="${BUN_CMD:-bun}"
|
||
elif command -v npx &>/dev/null; then
|
||
# Use npx to run bun commands – works on CI with setup-bun action
|
||
BUN_CMD="${BUN_CMD:-npx --yes bun}"
|
||
else
|
||
echo "ERROR: Neither bun nor npx found."
|
||
exit 1
|
||
fi
|
||
|
||
# Node/tsx for the fake GitHub server
|
||
if command -v tsx &>/dev/null; then
|
||
TSX_CMD="tsx"
|
||
elif command -v npx &>/dev/null; then
|
||
TSX_CMD="npx --yes tsx"
|
||
else
|
||
echo "ERROR: Neither tsx nor npx found."
|
||
exit 1
|
||
fi
|
||
|
||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||
echo "║ E2E Test Orchestrator ║"
|
||
echo "╠══════════════════════════════════════════════════════════════╣"
|
||
echo "║ Container runtime : $COMPOSE_CMD"
|
||
echo "║ Bun command : $BUN_CMD"
|
||
echo "║ TSX command : $TSX_CMD"
|
||
echo "║ Gitea URL : $GITEA_URL"
|
||
echo "║ Fake GitHub URL : $FAKE_GITHUB_URL"
|
||
echo "║ App URL : $APP_URL"
|
||
echo "║ Git Server URL : $GIT_SERVER_URL"
|
||
echo "║ Git Server (int) : $GIT_SERVER_INTERNAL_URL"
|
||
echo "║ CI mode : $CI_MODE"
|
||
echo "╚══════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
|
||
# ─── PID tracking for cleanup ─────────────────────────────────────────────────
|
||
FAKE_GITHUB_PID=""
|
||
APP_PID=""
|
||
EXIT_CODE=0
|
||
|
||
cleanup_on_exit() {
|
||
local code=$?
|
||
echo ""
|
||
echo "────────────────────────────────────────────────────────────────"
|
||
echo "[teardown] Cleaning up..."
|
||
|
||
# Kill fake GitHub server
|
||
if [[ -n "$FAKE_GITHUB_PID" ]] && kill -0 "$FAKE_GITHUB_PID" 2>/dev/null; then
|
||
echo "[teardown] Stopping fake GitHub server (PID $FAKE_GITHUB_PID)..."
|
||
kill "$FAKE_GITHUB_PID" 2>/dev/null || true
|
||
wait "$FAKE_GITHUB_PID" 2>/dev/null || true
|
||
fi
|
||
rm -f "$SCRIPT_DIR/.fake-github.pid"
|
||
|
||
# Kill app server
|
||
if [[ -n "$APP_PID" ]] && kill -0 "$APP_PID" 2>/dev/null; then
|
||
echo "[teardown] Stopping gitea-mirror app (PID $APP_PID)..."
|
||
kill "$APP_PID" 2>/dev/null || true
|
||
wait "$APP_PID" 2>/dev/null || true
|
||
fi
|
||
rm -f "$SCRIPT_DIR/.app.pid"
|
||
|
||
# Stop containers (unless --keep)
|
||
if [[ "$KEEP_RUNNING" == false ]]; then
|
||
if [[ -n "$COMPOSE_CMD" ]] && [[ -f "$COMPOSE_FILE" ]]; then
|
||
echo "[teardown] Stopping Gitea container..."
|
||
$COMPOSE_CMD -f "$COMPOSE_FILE" down --volumes --remove-orphans 2>/dev/null || true
|
||
fi
|
||
else
|
||
echo "[teardown] --keep flag set, leaving services running"
|
||
fi
|
||
|
||
echo "[teardown] Done."
|
||
|
||
# Use the test exit code, not the cleanup exit code
|
||
if [[ $EXIT_CODE -ne 0 ]]; then
|
||
exit $EXIT_CODE
|
||
fi
|
||
exit $code
|
||
}
|
||
|
||
trap cleanup_on_exit EXIT INT TERM
|
||
|
||
# ─── Step 0: Cleanup previous run ────────────────────────────────────────────
|
||
if [[ "${SKIP_CLEANUP:-false}" != "true" ]]; then
|
||
echo "┌──────────────────────────────────────────────────────────────┐"
|
||
echo "│ Step 0: Cleanup previous E2E run │"
|
||
echo "└──────────────────────────────────────────────────────────────┘"
|
||
bash "$SCRIPT_DIR/cleanup.sh" --soft 2>/dev/null || true
|
||
echo ""
|
||
fi
|
||
|
||
# ─── Step 1: Install dependencies ────────────────────────────────────────────
|
||
echo "┌──────────────────────────────────────────────────────────────┐"
|
||
echo "│ Step 1: Install dependencies │"
|
||
echo "└──────────────────────────────────────────────────────────────┘"
|
||
cd "$PROJECT_ROOT"
|
||
$BUN_CMD install 2>&1 | tail -5
|
||
echo "[deps] ✓ Dependencies installed"
|
||
|
||
# Install Playwright browsers if needed
|
||
if ! npx playwright install --dry-run chromium &>/dev/null 2>&1; then
|
||
echo "[deps] Installing Playwright browsers..."
|
||
npx playwright install chromium 2>&1 | tail -3
|
||
fi
|
||
# Always ensure system deps are available (needed in CI/fresh environments)
|
||
if [[ "$CI_MODE" == true ]]; then
|
||
echo "[deps] Installing Playwright system dependencies..."
|
||
npx playwright install-deps chromium 2>&1 | tail -5 || true
|
||
fi
|
||
echo "[deps] ✓ Playwright ready"
|
||
echo ""
|
||
|
||
# ─── Step 1.5: Create test git repositories ─────────────────────────────────
|
||
echo "┌──────────────────────────────────────────────────────────────┐"
|
||
echo "│ Step 1.5: Create test git repositories │"
|
||
echo "└──────────────────────────────────────────────────────────────┘"
|
||
|
||
GIT_REPOS_DIR="$SCRIPT_DIR/git-repos"
|
||
echo "[git-repos] Creating bare git repos in $GIT_REPOS_DIR ..."
|
||
$BUN_CMD run "$SCRIPT_DIR/create-test-repos.ts" --output-dir "$GIT_REPOS_DIR" 2>&1
|
||
|
||
if [[ ! -f "$GIT_REPOS_DIR/manifest.json" ]]; then
|
||
echo "ERROR: Test git repos were not created (manifest.json missing)"
|
||
EXIT_CODE=1
|
||
exit 1
|
||
fi
|
||
|
||
echo "[git-repos] ✓ Test repositories created"
|
||
echo ""
|
||
|
||
# ─── Step 2: Build the app ──────────────────────────────────────────────────
|
||
if [[ "$NO_BUILD" == false ]]; then
|
||
echo "┌──────────────────────────────────────────────────────────────┐"
|
||
echo "│ Step 2: Build gitea-mirror │"
|
||
echo "└──────────────────────────────────────────────────────────────┘"
|
||
cd "$PROJECT_ROOT"
|
||
|
||
# Initialize the database
|
||
echo "[build] Initializing database..."
|
||
$BUN_CMD run manage-db init 2>&1 | tail -3 || true
|
||
|
||
# Build the Astro project
|
||
echo "[build] Building Astro project..."
|
||
GITHUB_API_URL="$FAKE_GITHUB_URL" \
|
||
BETTER_AUTH_SECRET="e2e-test-secret" \
|
||
$BUN_CMD run build 2>&1 | tail -10
|
||
|
||
echo "[build] ✓ Build complete"
|
||
echo ""
|
||
else
|
||
echo "[build] Skipped (--no-build flag)"
|
||
echo ""
|
||
fi
|
||
|
||
# ─── Step 3: Start Gitea container ──────────────────────────────────────────
|
||
echo "┌──────────────────────────────────────────────────────────────┐"
|
||
echo "│ Step 3: Start Gitea container │"
|
||
echo "└──────────────────────────────────────────────────────────────┘"
|
||
|
||
$COMPOSE_CMD -f "$COMPOSE_FILE" up -d 2>&1
|
||
|
||
# Wait for git-server to be healthy first (Gitea depends on it)
|
||
echo "[git-server] Waiting for git HTTP server..."
|
||
GIT_SERVER_READY=false
|
||
for i in $(seq 1 30); do
|
||
if curl -sf "${GIT_SERVER_URL}/manifest.json" &>/dev/null; then
|
||
GIT_SERVER_READY=true
|
||
break
|
||
fi
|
||
printf "."
|
||
sleep 1
|
||
done
|
||
echo ""
|
||
|
||
if [[ "$GIT_SERVER_READY" != true ]]; then
|
||
echo "ERROR: Git HTTP server did not start within 30 seconds"
|
||
echo "[git-server] Container logs:"
|
||
$COMPOSE_CMD -f "$COMPOSE_FILE" logs git-server --tail=20 2>/dev/null || true
|
||
EXIT_CODE=1
|
||
exit 1
|
||
fi
|
||
echo "[git-server] ✓ Git HTTP server is ready on $GIT_SERVER_URL"
|
||
|
||
echo "[gitea] Waiting for Gitea to become healthy..."
|
||
GITEA_READY=false
|
||
for i in $(seq 1 60); do
|
||
if curl -sf "${GITEA_URL}/api/v1/version" &>/dev/null; then
|
||
GITEA_READY=true
|
||
break
|
||
fi
|
||
printf "."
|
||
sleep 2
|
||
done
|
||
echo ""
|
||
|
||
if [[ "$GITEA_READY" != true ]]; then
|
||
echo "ERROR: Gitea did not become healthy within 120 seconds"
|
||
echo "[gitea] Container logs:"
|
||
$COMPOSE_CMD -f "$COMPOSE_FILE" logs gitea-e2e --tail=30 2>/dev/null || true
|
||
EXIT_CODE=1
|
||
exit 1
|
||
fi
|
||
|
||
GITEA_VERSION=$(curl -sf "${GITEA_URL}/api/v1/version" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
|
||
echo "[gitea] ✓ Gitea is ready (version: ${GITEA_VERSION:-unknown})"
|
||
echo ""
|
||
|
||
# ─── Step 4: Start fake GitHub API ──────────────────────────────────────────
|
||
echo "┌──────────────────────────────────────────────────────────────┐"
|
||
echo "│ Step 4: Start fake GitHub API server │"
|
||
echo "└──────────────────────────────────────────────────────────────┘"
|
||
|
||
PORT=$FAKE_GITHUB_PORT GIT_SERVER_URL="$GIT_SERVER_INTERNAL_URL" \
|
||
$TSX_CMD "$SCRIPT_DIR/fake-github-server.ts" &
|
||
FAKE_GITHUB_PID=$!
|
||
echo "$FAKE_GITHUB_PID" > "$SCRIPT_DIR/.fake-github.pid"
|
||
|
||
echo "[fake-github] Started (PID: $FAKE_GITHUB_PID)"
|
||
echo "[fake-github] Waiting for server to be ready..."
|
||
|
||
FAKE_READY=false
|
||
for i in $(seq 1 30); do
|
||
if curl -sf "${FAKE_GITHUB_URL}/___mgmt/health" &>/dev/null; then
|
||
FAKE_READY=true
|
||
break
|
||
fi
|
||
# Check if process died
|
||
if ! kill -0 "$FAKE_GITHUB_PID" 2>/dev/null; then
|
||
echo "ERROR: Fake GitHub server process died"
|
||
EXIT_CODE=1
|
||
exit 1
|
||
fi
|
||
printf "."
|
||
sleep 1
|
||
done
|
||
echo ""
|
||
|
||
if [[ "$FAKE_READY" != true ]]; then
|
||
echo "ERROR: Fake GitHub server did not start within 30 seconds"
|
||
EXIT_CODE=1
|
||
exit 1
|
||
fi
|
||
|
||
echo "[fake-github] ✓ Fake GitHub API is ready on $FAKE_GITHUB_URL"
|
||
|
||
# Tell the fake GitHub server to use the git-server container URL for clone_url
|
||
# (This updates existing repos in the store so Gitea can actually clone them)
|
||
echo "[fake-github] Setting clone URL base to $GIT_SERVER_INTERNAL_URL ..."
|
||
curl -sf -X POST "${FAKE_GITHUB_URL}/___mgmt/set-clone-url" \
|
||
-H "Content-Type: application/json" \
|
||
-d "{\"url\": \"${GIT_SERVER_INTERNAL_URL}\"}" || true
|
||
echo "[fake-github] ✓ Clone URLs configured"
|
||
echo ""
|
||
|
||
# ─── Step 5: Start gitea-mirror app ────────────────────────────────────────
|
||
echo "┌──────────────────────────────────────────────────────────────┐"
|
||
echo "│ Step 5: Start gitea-mirror application │"
|
||
echo "└──────────────────────────────────────────────────────────────┘"
|
||
|
||
cd "$PROJECT_ROOT"
|
||
|
||
# Reinitialize the database in case build step reset it
|
||
$BUN_CMD run manage-db init 2>&1 | tail -2 || true
|
||
|
||
# Start the app with E2E environment
|
||
GITHUB_API_URL="$FAKE_GITHUB_URL" \
|
||
BETTER_AUTH_SECRET="e2e-test-secret" \
|
||
BETTER_AUTH_URL="$APP_URL" \
|
||
DATABASE_URL="file:data/gitea-mirror.db" \
|
||
HOST="0.0.0.0" \
|
||
PORT="$APP_PORT" \
|
||
NODE_ENV="production" \
|
||
PRE_SYNC_BACKUP_ENABLED="false" \
|
||
ENCRYPTION_SECRET="e2e-encryption-secret-32char!!" \
|
||
$BUN_CMD run start &
|
||
APP_PID=$!
|
||
echo "$APP_PID" > "$SCRIPT_DIR/.app.pid"
|
||
|
||
echo "[app] Started (PID: $APP_PID)"
|
||
echo "[app] Waiting for app to be ready..."
|
||
|
||
APP_READY=false
|
||
for i in $(seq 1 90); do
|
||
# Try the health endpoint first, then fall back to root
|
||
if curl -sf "${APP_URL}/api/health" &>/dev/null 2>&1 || \
|
||
curl -sf -o /dev/null -w "%{http_code}" "${APP_URL}/" 2>/dev/null | grep -q "^[23]"; then
|
||
APP_READY=true
|
||
break
|
||
fi
|
||
# Check if process died
|
||
if ! kill -0 "$APP_PID" 2>/dev/null; then
|
||
echo ""
|
||
echo "ERROR: gitea-mirror app process died"
|
||
EXIT_CODE=1
|
||
exit 1
|
||
fi
|
||
printf "."
|
||
sleep 2
|
||
done
|
||
echo ""
|
||
|
||
if [[ "$APP_READY" != true ]]; then
|
||
echo "ERROR: gitea-mirror app did not start within 180 seconds"
|
||
EXIT_CODE=1
|
||
exit 1
|
||
fi
|
||
|
||
echo "[app] ✓ gitea-mirror app is ready on $APP_URL"
|
||
echo ""
|
||
|
||
# ─── Step 6: Run Playwright E2E tests ──────────────────────────────────────
|
||
echo "┌──────────────────────────────────────────────────────────────┐"
|
||
echo "│ Step 6: Run Playwright E2E tests │"
|
||
echo "└──────────────────────────────────────────────────────────────┘"
|
||
|
||
cd "$PROJECT_ROOT"
|
||
|
||
# Ensure test-results directory exists
|
||
mkdir -p "$SCRIPT_DIR/test-results"
|
||
|
||
# Run Playwright
|
||
set +e
|
||
APP_URL="$APP_URL" \
|
||
GITEA_URL="$GITEA_URL" \
|
||
FAKE_GITHUB_URL="$FAKE_GITHUB_URL" \
|
||
npx playwright test \
|
||
--config "$SCRIPT_DIR/playwright.config.ts" \
|
||
--reporter=list
|
||
PLAYWRIGHT_EXIT=$?
|
||
set -e
|
||
|
||
echo ""
|
||
|
||
if [[ $PLAYWRIGHT_EXIT -eq 0 ]]; then
|
||
echo "═══════════════════════════════════════════════════════════════"
|
||
echo " ✅ E2E tests PASSED"
|
||
echo "═══════════════════════════════════════════════════════════════"
|
||
else
|
||
echo "═══════════════════════════════════════════════════════════════"
|
||
echo " ❌ E2E tests FAILED (exit code: $PLAYWRIGHT_EXIT)"
|
||
echo "═══════════════════════════════════════════════════════════════"
|
||
|
||
# On failure, dump some diagnostic info
|
||
echo ""
|
||
echo "[diag] Gitea container status:"
|
||
$COMPOSE_CMD -f "$COMPOSE_FILE" ps 2>/dev/null || true
|
||
echo ""
|
||
echo "[diag] Gitea container logs (last 20 lines):"
|
||
$COMPOSE_CMD -f "$COMPOSE_FILE" logs gitea-e2e --tail=20 2>/dev/null || true
|
||
echo ""
|
||
echo "[diag] Git server logs (last 10 lines):"
|
||
$COMPOSE_CMD -f "$COMPOSE_FILE" logs git-server --tail=10 2>/dev/null || true
|
||
echo ""
|
||
echo "[diag] Git server health:"
|
||
curl -sf "${GIT_SERVER_URL}/manifest.json" 2>/dev/null || echo "(unreachable)"
|
||
echo ""
|
||
echo "[diag] Fake GitHub health:"
|
||
curl -sf "${FAKE_GITHUB_URL}/___mgmt/health" 2>/dev/null || echo "(unreachable)"
|
||
echo ""
|
||
echo "[diag] App health:"
|
||
curl -sf "${APP_URL}/api/health" 2>/dev/null || echo "(unreachable)"
|
||
echo ""
|
||
|
||
# Point to HTML report
|
||
if [[ -d "$SCRIPT_DIR/playwright-report" ]]; then
|
||
echo "[diag] HTML report: $SCRIPT_DIR/playwright-report/index.html"
|
||
echo " Run: npx playwright show-report $SCRIPT_DIR/playwright-report"
|
||
fi
|
||
|
||
EXIT_CODE=$PLAYWRIGHT_EXIT
|
||
fi
|
||
|
||
# EXIT_CODE is used by the trap handler
|
||
exit $EXIT_CODE
|