Files
familysync/.planning/phases/08-gitea-ci/08-03-SUMMARY.md
T
Lucas Berger 982438dc10 style(13-03): apply Prettier formatting across repo
Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
2026-06-11 20:35:18 -04:00

12 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
08-gitea-ci 03 testing
playwright
ci
gitea
mariadb
webkit
chromium
dev-auth-bypass
phase provides
07-mobile-test-harness Phase 7 Playwright specs (both device profiles) run unchanged in CI
phase provides
08-02 ci.yml with fast-checks + api jobs; runner-mode (ubuntu-latest, Docker-executor, services:)
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
08-04
phase-09
phase-10
phase-11
phase-12
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
created modified
.gitea/workflows/ci.yml
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
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
CI-01
~2h (including CI iteration across 4 infrastructure fixes) 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:5173ECONNREFUSED.
  • 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