name: E2E Integration Tests on: push: branches: ["*"] paths-ignore: - "README.md" - "docs/**" - "CHANGELOG.md" - "LICENSE" - "www/**" - "helm/**" pull_request: branches: ["*"] paths-ignore: - "README.md" - "docs/**" - "CHANGELOG.md" - "LICENSE" - "www/**" - "helm/**" workflow_dispatch: inputs: debug_enabled: description: "Enable debug logging" required: false default: "false" type: boolean permissions: contents: read actions: read concurrency: group: e2e-${{ github.ref }} cancel-in-progress: true env: GITEA_PORT: 3333 FAKE_GITHUB_PORT: 4580 GIT_SERVER_PORT: 4590 APP_PORT: 4321 BUN_VERSION: "1.3.10" jobs: e2e-tests: name: E2E Integration Tests runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: ${{ env.BUN_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "22" - name: Install dependencies run: | bun install echo "✓ Dependencies installed" - name: Install Playwright run: | npx playwright install chromium npx playwright install-deps chromium echo "✓ Playwright ready" - name: Create test git repositories run: | echo "Creating bare git repos for E2E testing..." bun run tests/e2e/create-test-repos.ts --output-dir tests/e2e/git-repos if [ ! -f tests/e2e/git-repos/manifest.json ]; then echo "ERROR: Test git repos were not created (manifest.json missing)" exit 1 fi echo "✓ Test repos created:" cat tests/e2e/git-repos/manifest.json | jq -r '.repos[] | " • \(.owner)/\(.name) — \(.description)"' - name: Start Gitea and git-server containers run: | echo "Starting containers via docker compose..." docker compose -f tests/e2e/docker-compose.e2e.yml up -d # Wait for git-server echo "Waiting for git HTTP server..." for i in $(seq 1 30); do if curl -sf http://localhost:${{ env.GIT_SERVER_PORT }}/manifest.json > /dev/null 2>&1; then echo "✓ Git HTTP server is ready" break fi if [ $i -eq 30 ]; then echo "ERROR: Git HTTP server did not start" docker compose -f tests/e2e/docker-compose.e2e.yml logs git-server exit 1 fi sleep 1 done # Wait for Gitea echo "Waiting for Gitea to be ready..." for i in $(seq 1 60); do if curl -sf http://localhost:${{ env.GITEA_PORT }}/api/v1/version > /dev/null 2>&1; then version=$(curl -sf http://localhost:${{ env.GITEA_PORT }}/api/v1/version | jq -r '.version // "unknown"') echo "✓ Gitea is ready (version: $version)" break fi if [ $i -eq 60 ]; then echo "ERROR: Gitea did not become healthy within 120s" docker compose -f tests/e2e/docker-compose.e2e.yml logs gitea-e2e --tail=30 exit 1 fi sleep 2 done - name: Initialize database run: | bun run manage-db init echo "✓ Database initialized" - name: Build application env: GH_API_URL: http://localhost:4580 BETTER_AUTH_SECRET: e2e-test-secret run: | bun run build echo "✓ Build complete" - name: Start fake GitHub API server run: | # Start with GIT_SERVER_URL pointing to the git-server container name # (Gitea will resolve it via Docker networking) PORT=${{ env.FAKE_GITHUB_PORT }} GIT_SERVER_URL="http://git-server" \ npx tsx tests/e2e/fake-github-server.ts & echo $! > /tmp/fake-github.pid echo "Waiting for fake GitHub API..." for i in $(seq 1 30); do if curl -sf http://localhost:${{ env.FAKE_GITHUB_PORT }}/___mgmt/health > /dev/null 2>&1; then echo "✓ Fake GitHub API is ready" break fi if [ $i -eq 30 ]; then echo "ERROR: Fake GitHub API did not start" exit 1 fi sleep 1 done # Ensure clone URLs are set for the git-server container curl -sf -X POST http://localhost:${{ env.FAKE_GITHUB_PORT }}/___mgmt/set-clone-url \ -H "Content-Type: application/json" \ -d '{"url": "http://git-server"}' || true echo "✓ Clone URLs configured for git-server container" - name: Start gitea-mirror application env: GH_API_URL: http://localhost:4580 BETTER_AUTH_SECRET: e2e-test-secret BETTER_AUTH_URL: http://localhost:4321 DATABASE_URL: file:data/gitea-mirror.db HOST: 0.0.0.0 PORT: ${{ env.APP_PORT }} NODE_ENV: production PRE_SYNC_BACKUP_ENABLED: "false" ENCRYPTION_SECRET: "e2e-encryption-secret-32char!!" run: | # Re-init DB in case build step cleared it bun run manage-db init 2>/dev/null || true bun run start & echo $! > /tmp/app.pid echo "Waiting for gitea-mirror app..." for i in $(seq 1 90); do if curl -sf http://localhost:${{ env.APP_PORT }}/api/health > /dev/null 2>&1 || \ curl -sf -o /dev/null -w "%{http_code}" http://localhost:${{ env.APP_PORT }}/ 2>/dev/null | grep -q "^[23]"; then echo "✓ gitea-mirror app is ready" break fi if ! kill -0 $(cat /tmp/app.pid) 2>/dev/null; then echo "ERROR: App process died" exit 1 fi if [ $i -eq 90 ]; then echo "ERROR: gitea-mirror app did not start within 180s" exit 1 fi sleep 2 done - name: Run E2E tests env: APP_URL: http://localhost:${{ env.APP_PORT }} GITEA_URL: http://localhost:${{ env.GITEA_PORT }} FAKE_GITHUB_URL: http://localhost:${{ env.FAKE_GITHUB_PORT }} GIT_SERVER_URL: http://localhost:${{ env.GIT_SERVER_PORT }} CI: true run: | mkdir -p tests/e2e/test-results npx playwright test \ --config tests/e2e/playwright.config.ts \ --reporter=github,html - name: Diagnostic info on failure if: failure() run: | echo "═══════════════════════════════════════════════════════════" echo " Diagnostic Information" echo "═══════════════════════════════════════════════════════════" echo "" echo "── Git server status ──" curl -sf http://localhost:${{ env.GIT_SERVER_PORT }}/manifest.json 2>/dev/null | jq . || echo "(unreachable)" echo "" echo "── Gitea status ──" curl -sf http://localhost:${{ env.GITEA_PORT }}/api/v1/version 2>/dev/null || echo "(unreachable)" echo "" echo "── Fake GitHub status ──" curl -sf http://localhost:${{ env.FAKE_GITHUB_PORT }}/___mgmt/health 2>/dev/null | jq . || echo "(unreachable)" echo "" echo "── App status ──" curl -sf http://localhost:${{ env.APP_PORT }}/api/health 2>/dev/null || echo "(unreachable)" echo "" echo "── Docker containers ──" docker compose -f tests/e2e/docker-compose.e2e.yml ps 2>/dev/null || true echo "" echo "── Gitea container logs (last 50 lines) ──" docker compose -f tests/e2e/docker-compose.e2e.yml logs gitea-e2e --tail=50 2>/dev/null || echo "(no container)" echo "" echo "── Git server logs (last 20 lines) ──" docker compose -f tests/e2e/docker-compose.e2e.yml logs git-server --tail=20 2>/dev/null || echo "(no container)" echo "" echo "── Running processes ──" ps aux | grep -E "(fake-github|astro|bun|node)" | grep -v grep || true - name: Upload Playwright report uses: actions/upload-artifact@v4 if: always() with: name: e2e-playwright-report path: tests/e2e/playwright-report/ retention-days: 14 - name: Upload test results uses: actions/upload-artifact@v4 if: always() with: name: e2e-test-results path: tests/e2e/test-results/ retention-days: 14 - name: Cleanup if: always() run: | # Stop background processes if [ -f /tmp/fake-github.pid ]; then kill $(cat /tmp/fake-github.pid) 2>/dev/null || true rm -f /tmp/fake-github.pid fi if [ -f /tmp/app.pid ]; then kill $(cat /tmp/app.pid) 2>/dev/null || true rm -f /tmp/app.pid fi # Stop containers docker compose -f tests/e2e/docker-compose.e2e.yml down --volumes --remove-orphans 2>/dev/null || true echo "✓ Cleanup complete"