Bugfix/e2e stress test fixes #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Runs lint, unit tests, and E2E suites to gate deployments | |
| name: Test | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| jobs: | |
| test: | |
| name: Test Suite | |
| runs-on: ubuntu-latest | |
| env: | |
| CONVERTKIT_API_KEY: ${{ secrets.CONVERTKIT_API_KEY }} | |
| CONVERTKIT_FORM_ID: ${{ secrets.CONVERTKIT_FORM_ID }} | |
| CRON_SECRET: ${{ secrets.CRON_SECRET }} | |
| RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }} | |
| SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
| SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | |
| SUPABASE_URL: ${{ secrets.SUPABASE_URL }} | |
| SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} | |
| SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }} | |
| SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} | |
| SUPABASE_PROJECT_REF: ${{ secrets.SUPABASE_PROJECT_REF }} | |
| SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_DB_PASSWORD }} | |
| KV_URL: ${{ secrets.KV_URL }} | |
| KV_REST_API_URL: ${{ secrets.KV_REST_API_URL }} | |
| KV_REST_API_TOKEN: ${{ secrets.KV_REST_API_TOKEN }} | |
| KV_REST_API_READ_ONLY_TOKEN: ${{ secrets.KV_REST_API_READ_ONLY_TOKEN }} | |
| REDIS_URL: ${{ secrets.REDIS_URL }} | |
| WEBMENTION_IO_TOKEN: ${{ secrets.WEBMENTION_IO_TOKEN }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Determine hotfix skip | |
| id: branch-filter | |
| shell: bash | |
| run: | | |
| ref="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" | |
| if [[ "$ref" == hotfix/* ]]; then | |
| echo "skip_tests=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip_tests=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Skip notice for hotfix branch | |
| if: steps.branch-filter.outputs.skip_tests == 'true' | |
| run: | | |
| echo "hotfix/* branch detected; skipping lint and test steps." | |
| - name: Setup Node.js | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22.x' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm ci --legacy-peer-deps | |
| - name: Sync Astro types | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run sync | |
| - name: Run Astro check | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run check | |
| - name: Run lint | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run lint | |
| - name: Run unit tests (Vitest — coverage with GitHub Actions reporter) | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| id: vitest | |
| run: | | |
| npm run test:coverage | |
| - name: Report Coverage | |
| if: steps.branch-filter.outputs.skip_tests != 'true' && steps.vitest.outcome == 'success' && hashFiles('coverage/coverage-summary.json') != '' | |
| uses: davelosert/vitest-coverage-report-action@v2.9.0 | |
| with: | |
| json-summary-path: './coverage/coverage-summary.json' | |
| json-final-path: './coverage/coverage-final.json' | |
| - name: Install Playwright browsers | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npx playwright install --with-deps | |
| - name: Set up Docker Buildx | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| uses: docker/setup-buildx-action@v3.11.1 | |
| - name: Build Upstash mock image | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: docker buildx build --load -t wb/upstash-redis-local:test test/containers/upstash/local-proxy | |
| - name: Generate container env file | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p test/containers | |
| : "${SUPABASE_SERVICE_ROLE_KEY:?SUPABASE_SERVICE_ROLE_KEY secret is required}" | |
| cat <<EOF > test/containers/.env | |
| COMPOSE_PROJECT_NAME=wb-e2e | |
| CONVERTKIT_HTTP_PORT=9010 | |
| RESEND_HTTP_PORT=9011 | |
| UPSTASH_HTTP_PORT=${UPSTASH_HTTP_PORT:-8079} | |
| UPSTASH_REDIS_PORT=${UPSTASH_REDIS_PORT:-6380} | |
| UPSTASH_TOKEN=${UPSTASH_TOKEN:-local-dev-token} | |
| SUPABASE_HEALTH_TIMEOUT=${SUPABASE_HEALTH_TIMEOUT:-240} | |
| SUPABASE_URL=${SUPABASE_URL:-http://127.0.0.1:54321} | |
| SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY} | |
| EOF | |
| - name: Start mock containers | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run containers:up | |
| - name: Wait for mock services | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run containers:wait | |
| - name: Start Supabase stack | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run containers:supabase:start | |
| - name: Apply Supabase migrations (local container) | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run containers:supabase:db-push | |
| - name: Start Astro dev server | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: | | |
| npm run dev -- --host 0.0.0.0 > /tmp/astro-dev.log 2>&1 & | |
| echo $! > /tmp/astro-dev.pid | |
| - name: Wait for dev server | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: | | |
| for attempt in $(seq 1 60); do | |
| if curl -fsS http://127.0.0.1:4321 >/dev/null; then | |
| echo "✅ Dev server is responding" | |
| exit 0 | |
| fi | |
| sleep 2 | |
| done | |
| echo "❌ Dev server failed to start" >&2 | |
| if [ -f /tmp/astro-dev.log ]; then | |
| echo '--- Astro dev server log ---' | |
| cat /tmp/astro-dev.log | |
| fi | |
| exit 1 | |
| - name: Run Playwright E2E tests | |
| if: steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npx playwright test | |
| env: | |
| CI: '1' | |
| FORCE_COLOR: '1' | |
| E2E_MOCKS: '1' | |
| - name: Stop Astro dev server | |
| if: always() && steps.branch-filter.outputs.skip_tests != 'true' | |
| run: | | |
| if [ -f /tmp/astro-dev.pid ]; then | |
| kill $(cat /tmp/astro-dev.pid) || true | |
| rm /tmp/astro-dev.pid | |
| fi | |
| - name: Upload Playwright report | |
| if: always() && steps.branch-filter.outputs.skip_tests != 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: playwright-report | |
| path: playwright-report/ | |
| retention-days: 30 | |
| - name: Upload test coverage | |
| if: always() && steps.branch-filter.outputs.skip_tests != 'true' | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: test-coverage | |
| path: coverage/ | |
| retention-days: 30 | |
| - name: Stop Supabase stack | |
| if: always() && steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run containers:supabase:stop || true | |
| - name: Stop mock containers | |
| if: always() && steps.branch-filter.outputs.skip_tests != 'true' | |
| run: npm run containers:down || true |