From 53a989c3fb9e1d3aad45b9dabb058f4fa107b248 Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Thu, 11 Jun 2026 15:05:04 -0400 Subject: [PATCH] =?UTF-8?q?fix(08-03):=20keep=20API=20alive=20during=20har?= =?UTF-8?q?ness=20=E2=80=94=20start=20API=20+=20run=20e2e=20in=20one=20ste?= =?UTF-8?q?p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run #7 harness failed: global-setup polled :5173/health (Vite proxy → :3000) and never got 200. The API connected to the DB and :3000/health was green during the separate 'Wait for API' step, but the bare-backgrounded node process was reaped at the step boundary and was dead by the time the e2e step ran (after the multi-minute browser install). Confirmed locally the API does not self-crash (alive + healthy for 75s in-shell). Install browsers first, then start the API and run Playwright in a SINGLE step so the API stays a child of the test shell for the whole run; capture the test exit code and kill the API after. No harness files touched. --- .gitea/workflows/ci.yml | 73 +++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index ecb9bed..d1f2429 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -212,47 +212,25 @@ jobs: - name: Build API run: pnpm --filter @familysync/api build - # Start the API as a background process. - # DEV_AUTH_BYPASS=true is passed INLINE on the node line (Pitfall 8 — env inheritance - # across & steps is not guaranteed in all runner modes). NODE_ENV=development is required: - # global-setup.ts refuses NODE_ENV=production, and the API devBypass.ts checks development. - - name: Start API background process - run: | - NODE_ENV=development DEV_AUTH_BYPASS=true DB_HOST=$DB_HOST DB_PORT=3306 DB_USER=familysync DB_PASSWORD=testpass DB_NAME=familysync node apps/api/dist/index.js & - echo $! > /tmp/api.pid - echo "API PID: $(cat /tmp/api.pid)" - - # Wait for the API :3000/health before Playwright starts (D-02 / T-08-08). - # This step-level wait is SEPARATE from global-setup.ts's poll — global-setup runs AFTER - # Playwright starts and polls through the Vite proxy. The step-level wait ensures the API - # is up before Playwright even attempts to start Vite. ~60s deadline. - - name: Wait for API (:3000/health) - run: | - deadline=$((SECONDS + 60)) - until curl -sf http://localhost:3000/health > /dev/null 2>&1; do - if [ $SECONDS -ge $deadline ]; then - echo "API did not start within 60s" - kill $(cat /tmp/api.pid) 2>/dev/null || true - exit 1 - fi - sleep 2 - done - echo "API ready at :3000" - - # Install Playwright browsers with system deps. + # Install Playwright browsers with system deps BEFORE starting the API, so the long + # browser download does not run during the API's lifetime. # Must run from apps/pwa/ where @playwright/test is installed (D-PROBE-05 confirmed exit 0). # Do NOT cache browser binaries — Playwright explicitly recommends against it in CI. - name: Install Playwright browsers run: npx playwright install --with-deps webkit chromium working-directory: apps/pwa - # Run the Phase 7 Playwright harness across both device profiles (iphone + pixel). - # CI=true makes Playwright: start Vite :5173 itself (reuseExistingServer=false), - # use retries:2/workers:1, and apply reporter:'github' from config — which we - # override with --reporter=list,html because Gitea does not render github annotations - # (Pitfall 5 / D-06). Both projects run by default (no --project filter). - - name: Run Playwright harness (iphone + pixel) - run: pnpm test:e2e -- --reporter=list,html + # Start the API AND run the harness in ONE step. A bare `node &` started in an EARLIER + # step is reaped at the step boundary: CI run #7 proved :3000 was healthy during a + # separate "wait" step but dead by the time global-setup polled :5173/health → :3000 + # (after the multi-minute browser install). Keeping the API a child of THIS step's shell + # guarantees it stays alive for the entire Playwright run. + # DEV_AUTH_BYPASS=true + NODE_ENV=development are set both inline and in env: — global-setup.ts + # refuses NODE_ENV=production and the API devBypass.ts checks development. DB_* come from env:. + # CI=true makes Playwright start Vite :5173 itself (reuseExistingServer=false), use + # retries:2/workers:1, and apply reporter:'github' — which --reporter=list,html overrides + # because Gitea does not render github annotations (Pitfall 5 / D-06). Both projects run. + - name: Run harness (start API + Playwright iphone + pixel) env: CI: 'true' PLAYWRIGHT_BASE_URL: http://localhost:5173 @@ -263,6 +241,26 @@ jobs: DB_USER: familysync DB_PASSWORD: testpass DB_NAME: familysync + run: | + NODE_ENV=development DEV_AUTH_BYPASS=true node apps/api/dist/index.js & + API_PID=$! + echo "API PID: $API_PID" + + # Wait for the API :3000/health before launching Playwright (D-02 / T-08-08). + deadline=$((SECONDS + 60)) + until curl -sf http://localhost:3000/health > /dev/null 2>&1; do + if ! kill -0 "$API_PID" 2>/dev/null; then echo "API process exited before becoming ready"; exit 1; fi + if [ $SECONDS -ge $deadline ]; then echo "API did not become ready within 60s"; kill "$API_PID" 2>/dev/null || true; exit 1; fi + sleep 2 + done + echo "API ready at :3000" + + # Run the Phase 7 harness across both profiles; preserve its exit code, always kill the API. + set +e + pnpm test:e2e -- --reporter=list,html + rc=$? + kill "$API_PID" 2>/dev/null || true + exit $rc # Upload traces/screenshots/videos on failure for debugging (D-06). # MUST use ChristopherHX/gitea-upload-artifact@v4 — the standard upload-artifact action @@ -274,8 +272,3 @@ jobs: name: playwright-traces-${{ github.run_id }} path: apps/pwa/test-results/ retention-days: 14 - - # Always kill the API background process to clean up, even on success. - - name: Kill API background process - if: always() - run: kill $(cat /tmp/api.pid) 2>/dev/null || true