docs(08-03): SUMMARY — harness green, 58 specs both profiles on cold CI stack
- Run #11 (PR #3): 58 passed in 1.6 min (iphone/WebKit + pixel/Chromium) - 4 infrastructure fixes: API-reap at step boundary, IPv4-first for Vite, dev-user FK seed, reporter double-forward via pnpm - No Phase 7 harness file modified (phase boundary D-01/D-02 held) - Advance position to 08-04 (publish job)
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
---
|
||||
phase: 08-gitea-ci
|
||||
plan: 03
|
||||
subsystem: testing
|
||||
tags: [playwright, ci, gitea, mariadb, webkit, chromium, dev-auth-bypass]
|
||||
|
||||
# Dependency graph
|
||||
requires:
|
||||
- phase: 07-mobile-test-harness
|
||||
provides: Phase 7 Playwright specs (both device profiles) run unchanged in CI
|
||||
- phase: 08-02
|
||||
provides: ci.yml with fast-checks + api jobs; runner-mode (ubuntu-latest, Docker-executor, services:)
|
||||
provides:
|
||||
- harness job in .gitea/workflows/ci.yml bringing up the full dev stack in CI and running the Phase 7 mobile specs across both device profiles
|
||||
- four infrastructure fixes resolving API-reap, IPv6/IPv4 mismatch, missing dev-user seed, and double-pnpm reporter forwarding
|
||||
affects: [08-04, phase-09, phase-10, phase-11, phase-12]
|
||||
|
||||
# Tech tracking
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "Combine API-start + readiness + test run in a single CI step so the API is not reaped at a step boundary"
|
||||
- "NODE_OPTIONS=--dns-result-order=ipv4first when Vite is IPv4-only and the runner resolves localhost to ::1 first"
|
||||
- "Idempotent seed step (INSERT IGNORE) for the DEV_AUTH_BYPASS user before global-setup runs — FK chain requires it"
|
||||
- "Call the PWA test:e2e script directly with --filter instead of root test:e2e -- -- to avoid double-pnpm arg forwarding"
|
||||
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- .gitea/workflows/ci.yml
|
||||
|
||||
key-decisions:
|
||||
- "FIX-1 (53a989c): Start API + run e2e in a single step — bare 'node &' in an early step is reaped when that step exits; the API must remain a child of the test shell through the entire Playwright run"
|
||||
- "FIX-2 (7389740): Use PLAYWRIGHT_BASE_URL=http://127.0.0.1:5173 and NODE_OPTIONS=--dns-result-order=ipv4first — Vite binds IPv4-only; Node fetch does not fall back from ::1 to 127.0.0.1 unlike curl"
|
||||
- "FIX-3 (e486c6b): Seed dev user id=1 (INSERT IGNORE) after migrate, before API start — DEV_AUTH_BYPASS injects the user in-memory only; on a fresh CI DB the FK constraint silently aborted the calendars seed"
|
||||
- "FIX-4 (03e8088): Call 'pnpm --filter @familysync/pwa test:e2e --reporter=list,html' directly — 'pnpm test:e2e -- --reporter=list,html' double-forwards '--' through two pnpm layers; Playwright treats --reporter as a test-file filter and finds no tests"
|
||||
- "Phase 7 harness files (playwright.config.ts, global-setup.ts, vite.config.ts, all specs) were NOT modified — CI owns stack bring-up only (D-01/D-02 phase boundary held)"
|
||||
- "Reporter override --reporter=list,html kept: Gitea does not render 'github' annotations; list output is legible in the log"
|
||||
|
||||
patterns-established:
|
||||
- "Harness step pattern: install browsers, then start API + wait for :3000/health, then run Playwright — all in one step"
|
||||
- "Idempotent user seed step: INSERT IGNORE + upsert pattern for DEV_AUTH_BYPASS user before global-setup's FK-dependent seeds"
|
||||
|
||||
requirements-completed: [CI-01]
|
||||
|
||||
# Metrics
|
||||
duration: ~2h (including CI iteration across 4 infrastructure fixes)
|
||||
completed: 2026-06-11
|
||||
---
|
||||
|
||||
# Phase 08 Plan 03: Harness CI Job Summary
|
||||
|
||||
**Gitea Actions harness job brings up MariaDB + API (DEV_AUTH_BYPASS) + Playwright Vite on every PR and runs 58 Phase 7 specs across iPhone/WebKit + Pixel/Chromium in 1.6 min — four infrastructure fixes required, no harness file modified**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** ~2h (task authoring + 4 CI fix iterations)
|
||||
- **Started:** 2026-06-11
|
||||
- **Completed:** 2026-06-11
|
||||
- **Tasks:** 2 auto + 1 checkpoint (human-verified)
|
||||
- **Files modified:** 1 (.gitea/workflows/ci.yml)
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Harness job added to ci.yml: MariaDB 11 service → migrate → seed dev user → API background (DEV_AUTH_BYPASS=true, :3000) → Playwright starts Vite (:5173) → both iphone (WebKit) + pixel (Chromium) profiles → traces upload on failure
|
||||
- 58 Phase 7 specs passed green on Gitea Actions run #11 (PR #3, pull_request) — cold CI stack, 1.6 min
|
||||
- All four CI-side infrastructure fixes resolved without touching any Phase 7 harness file (phase boundary D-01/D-02 held)
|
||||
- Artifact upload confirmed working: playwright-traces-10 downloaded from Gitea UI on run #10
|
||||
|
||||
## Task Commits
|
||||
|
||||
1. **Task 1: Add harness job — DB + migrate + API background + :3000 readiness** - `d55e347` (feat)
|
||||
2. **Task 2: Add Playwright install + run (both profiles) + artifact upload** - `71c8909` (feat)
|
||||
3. **Fix 1: Keep API alive during harness — start API + run e2e in one step** - `53a989c` (fix)
|
||||
4. **Fix 2: Harness uses 127.0.0.1 + ipv4first — Vite is IPv4-only** - `7389740` (fix)
|
||||
5. **Fix 3: Seed dev user id=1 — global-setup assumes it exists** - `e486c6b` (fix)
|
||||
6. **Fix 4: Call pwa test:e2e directly so --reporter forwards cleanly** - `03e8088` (fix)
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `.gitea/workflows/ci.yml` — harness job added; fast-checks + api jobs unchanged
|
||||
|
||||
## Decisions Made
|
||||
|
||||
**D-08-03-COMBINE-STEP:** API start + readiness wait + `pnpm test:e2e` run combined into a single CI step. When the API was started with `node &` in a standalone step, the backgrounded process was reaped when that step exited — the multi-minute browser install that followed caused the API to die before the test step. Confirmed the API does not self-crash when left as a background child of the test shell.
|
||||
|
||||
**D-08-03-IPV4FIRST:** `PLAYWRIGHT_BASE_URL=http://127.0.0.1:5173` and `NODE_OPTIONS=--dns-result-order=ipv4first` set on the harness step. The Gitea runner resolves `localhost` to `::1` (IPv6) first; Vite binds IPv4-only (`127.0.0.1:5173`); Node `fetch` does not fall back to IPv4 unlike `curl`. Proven: `[::1]:5173 ECONNREFUSED` vs `127.0.0.1:5173 200`. The API is dual-stack so its `localhost:3000` references were unaffected.
|
||||
|
||||
**D-08-03-SEED-USER:** An idempotent "Seed dev user (id=1)" step runs after `db:migrate` and before the API starts. `DEV_AUTH_BYPASS` in `devBypass.ts` injects the user entirely in-memory — on a fresh CI database there is no `users` row, so the `global-setup.ts` `INSERT IGNORE INTO calendars` silently fails on the FK constraint and calendar id=10 is absent, causing a cascade FK error on `calendar_events`. The seed is `INSERT IGNORE INTO users (id, oidc_iss, oidc_sub, display_name, color) VALUES (1, 'dev', 'dev-user', 'Dev User', '#4A90D9')`.
|
||||
|
||||
**D-08-03-REPORTER-FORWARD:** The root `test:e2e` script is `pnpm --filter @familysync/pwa test:e2e`. Calling `pnpm test:e2e -- --reporter=list,html` from the root passes `--` through two pnpm layers, resulting in `playwright test -- --reporter=list,html` where `--reporter=list,html` is treated as a test-file path filter — Playwright finds no tests. Fix: call `pnpm --filter @familysync/pwa test:e2e --reporter=list,html` directly. Validated: 58 specs listed vs 0 with the broken invocation.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues (all Rule 3 — blocking)
|
||||
|
||||
**1. [Rule 3 - Blocking] API reaped at step boundary**
|
||||
- **Found during:** CI run after Task 1+2 commits
|
||||
- **Issue:** Bare `node apps/api/dist/index.js &` in an early step was reaped when that step exited. The browser install (multi-minute) ran next, then the test step found no API.
|
||||
- **Fix:** Merged API start + curl :3000/health readiness loop + `pnpm test:e2e` into a single step; moved browser install to the step immediately before it.
|
||||
- **Files modified:** .gitea/workflows/ci.yml
|
||||
- **Committed in:** 53a989c
|
||||
|
||||
**2. [Rule 3 - Blocking] global-setup ECONNREFUSED on Vite :5173**
|
||||
- **Found during:** CI run post fix 1
|
||||
- **Issue:** `global-setup.ts` fetched `${PLAYWRIGHT_BASE_URL}/health`; `PLAYWRIGHT_BASE_URL` defaulted to `http://localhost:5173`; runner resolved `localhost` → `::1`; Vite bound only `127.0.0.1:5173` → `ECONNREFUSED`.
|
||||
- **Fix:** Added `PLAYWRIGHT_BASE_URL: http://127.0.0.1:5173` and `NODE_OPTIONS: --dns-result-order=ipv4first` to the harness step env.
|
||||
- **Files modified:** .gitea/workflows/ci.yml
|
||||
- **Committed in:** 7389740
|
||||
|
||||
**3. [Rule 3 - Blocking] Missing dev user id=1 causes FK error in global-setup seed**
|
||||
- **Found during:** CI run post fix 2
|
||||
- **Issue:** `global-setup.ts` seeds `calendars` + `calendar_events` for `user_id=1`. `DEV_AUTH_BYPASS` injects that user in-memory only (no DB row). On a fresh CI DB, the `INSERT IGNORE INTO calendars` silently aborted on the `users` FK; calendar id=10 was absent; the `calendar_events` insert then failed on the calendars FK.
|
||||
- **Fix:** Added a "Seed dev user" step after `db:migrate`: `INSERT IGNORE INTO users` with `id=1, oidc_iss='dev', oidc_sub='dev-user', display_name='Dev User', color='#4A90D9'`.
|
||||
- **Files modified:** .gitea/workflows/ci.yml
|
||||
- **Committed in:** e486c6b
|
||||
|
||||
**4. [Rule 3 - Blocking] --reporter flag treated as test-file filter**
|
||||
- **Found during:** CI run post fix 3
|
||||
- **Issue:** `pnpm test:e2e -- --reporter=list,html` from the workspace root double-forwarded `--` through two pnpm invocations, delivering `playwright test -- --reporter=list,html`; Playwright interpreted `--reporter=list,html` as a test-file path and found no tests.
|
||||
- **Fix:** Changed invocation to `pnpm --filter @familysync/pwa test:e2e --reporter=list,html` — bypasses the root script delegation entirely.
|
||||
- **Files modified:** .gitea/workflows/ci.yml
|
||||
- **Committed in:** 03e8088
|
||||
|
||||
---
|
||||
|
||||
**Total deviations:** 4 auto-fixed (all Rule 3 — blocking CI failures). All were infrastructure/orchestration issues. No Phase 7 harness files (playwright.config.ts, global-setup.ts, vite.config.ts, or any spec) were modified.
|
||||
|
||||
## Verified CI Result
|
||||
|
||||
**Gitea Actions run #11** (PR #3, `pull_request` event) — conclusion **SUCCESS**
|
||||
|
||||
- **Harness result:** 58 passed in 1.6 min
|
||||
- **Profiles:** iphone (WebKit) + pixel (Chromium), both passing
|
||||
- **Co-running jobs:** fast-checks (191 PWA tests) + api (238 API tests) — all green in the same run
|
||||
- **Artifact upload:** Confirmed working on run #10 — `playwright-traces-10` uploaded with a download URL via `ChristopherHX/gitea-upload-artifact@v4`
|
||||
- **Phase boundary:** Zero Phase 7 files modified — confirmed via `git diff --quiet -- apps/pwa/playwright.config.ts apps/pwa/e2e/global-setup.ts apps/pwa/vite.config.ts`
|
||||
|
||||
## CI Stack Bring-Up Order (confirmed working)
|
||||
|
||||
1. `services: mariadb:11` container (DB_HOST=mariadb, Docker-executor mode)
|
||||
2. `actions/checkout@v4` + `setup-node@v4` (Node 22) + `corepack enable pnpm`
|
||||
3. `pnpm install --frozen-lockfile`
|
||||
4. mysql2 readiness loop until mariadb port 3306 accepts connections
|
||||
5. `pnpm --filter @familysync/api db:migrate` (never push — verified no `db:push` in ci.yml)
|
||||
6. Seed dev user id=1 (INSERT IGNORE — idempotent)
|
||||
7. `pnpm --filter @familysync/api build` → dist/index.js
|
||||
8. `npx playwright install --with-deps webkit chromium` (from apps/pwa working-directory)
|
||||
9. Combined step: `NODE_ENV=development DEV_AUTH_BYPASS=true ... node apps/api/dist/index.js &` → curl :3000/health readiness loop → `pnpm --filter @familysync/pwa test:e2e --reporter=list,html`
|
||||
10. `if: failure()` — artifact upload via `ChristopherHX/gitea-upload-artifact@v4`
|
||||
11. `if: always()` — kill API background process
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
WebKit deps install: clean exit 0 — confirmed on this runner (D-PROBE-05 from plan 01, re-verified here). No issues encountered.
|
||||
|
||||
Reporter legibility: `list` reporter produced readable per-test output in the Gitea log; `html` report built but is only accessible via artifact download.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None.
|
||||
|
||||
## Threat Flags
|
||||
|
||||
None — no new network endpoints or auth paths introduced. The `DEV_AUTH_BYPASS=true` flag is scoped to the harness job only; it does not appear in the publish job (Plan 04). Threat mitigations T-08-06, T-08-07, T-08-08 confirmed implemented.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
- Plan 04 (publish job) is unblocked: harness green, CI-01 harness half complete
|
||||
- ROADMAP CI-01 criteria 3 (failure gates merge) and 4 (readiness waits) satisfied
|
||||
- Plan 04 needs `GITEA_REGISTRY_PAT` (deferred D-PROBE-08) — operator must create the PAT before the publish step can push to the Gitea container registry
|
||||
|
||||
---
|
||||
*Phase: 08-gitea-ci*
|
||||
*Completed: 2026-06-11*
|
||||
Reference in New Issue
Block a user