15 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 08-gitea-ci | 03 | execute | 3 |
|
|
false |
|
|
Purpose: Catch mobile-only regressions on every PR with no developer's host stack required (Phase 7 success criterion 4). CI owns ONLY stack bring-up + readiness waits — never spec content (D-01/D-02; 08-CONTEXT phase boundary).
Output: a harness job in ci.yml gated on pull_request → main.
The orchestration order in 08-RESEARCH §Dev-Stack Bring-Up is mandatory and SEQUENTIAL within the job. Read 08-01-SUMMARY for the runner-mode DB path and the WebKit-deps / upload-artifact answers.
<execution_context> @$HOME/.claude/gsd-core/workflows/execute-plan.md @$HOME/.claude/gsd-core/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/08-gitea-ci/08-RESEARCH.md @.planning/research/PITFALLS.md @.planning/phases/08-gitea-ci/08-01-SUMMARY.md @apps/pwa/playwright.config.ts @apps/pwa/e2e/global-setup.ts @apps/pwa/vite.config.ts<artifacts_this_phase_produces>
.gitea/workflows/ci.yml(EXTENDED — adds the harness job; created in Plan 02) </artifacts_this_phase_produces>
<interface_context> Confirmed harness contract (from playwright.config.ts + global-setup.ts + vite.config.ts — do NOT modify these files):
playwright.config.ts:reuseExistingServer: !process.env.CI→ with CI=true, Playwright STARTS Vite itself (pnpm --filter @familysync/pwa dev, :5173).retries: 2,workers: 1,reporter: 'github'are all gated onprocess.env.CI. Two projects:iphone(WebKit) +pixel(Chromium), bothserviceWorkers: 'block'.reporter: 'github'likely emits invisible output in Gitea (08-RESEARCH Pitfall 5 / D-06). Override the reporter at the CI invocation: pass--reporter=list,html(e.g.pnpm test:e2e -- --reporter=list,html) OR confirm from 08-01-SUMMARY whether Gitea rendered annotations; if it did, the override is harmless. Do NOT edit playwright.config.ts.global-setup.ts: FAILS CLOSED — throws ifNODE_ENV=productionOR ifDEV_AUTH_BYPASS !== 'true'. It polls${PLAYWRIGHT_BASE_URL}/health(via the Vite proxy → :3000), then gates/api/me(must be 200 → proves DEV_AUTH_BYPASS reached the API), then mysql2-seeds calendar id=10 + lists for user 1. It reads DB_HOST/DB_PORT/DB_USER/DB_PASSWORD/DB_NAME (DB_HOST default 127.0.0.1).vite.config.ts: dev proxy/health,/api,/callback→ http://localhost:3000. So PLAYWRIGHT_BASE_URL=http://localhost:5173 reaches the API health endpoint through the proxy.- Root
test:e2e=pnpm --filter @familysync/pwa test:e2e=playwright test. - API start:
devscript isnode --watch dist/index.jsand needs a prior build. In CI runpnpm --filter @familysync/api build(tsc → dist/index.js) thennode apps/api/dist/index.js &(no --watch; the watcher is irrelevant in CI — Claude's Discretion in D + 08-RESEARCH Pattern 3). Pass DEV_AUTH_BYPASS=true INLINE on the node line (Pitfall 8 — env inheritance across&steps is not guaranteed). npx playwright install --with-deps webkit chromiummust run fromapps/pwa(where @playwright/test lives). Playwright explicitly says do NOT cache browser binaries (08-RESEARCH).- DEV_AUTH_BYPASS user 1 has no CalDAV credential → harness verifies layout/flows, not live event-create (project memory). Specs already account for this; no change. </interface_context>
DB bring-up: SAME runner-mode branch as Plan 02's api job (services: mariadb: for Docker mode with DB_HOST=mariadb, or `docker run -d` + readiness loop for host mode with DB_HOST=127.0.0.1). Set job env: DB_PORT 3306, DB_USER familysync, DB_PASSWORD testpass, DB_NAME familysync (throwaway creds). Include the explicit healthcheck.sh readiness loop before migrate (Pitfall 11; never mysqladmin).
Steps, in this exact order (08-RESEARCH §Dev-Stack Bring-Up 1..6):
1. `uses: actions/checkout@v4`; `uses: actions/setup-node@v4` (node 22); `corepack enable pnpm`.
2. `run: pnpm install --frozen-lockfile`.
3. (after DB ready) `run: pnpm --filter @familysync/api db:migrate` with DB_* env (drizzle-kit migrate; never push).
4. `run: pnpm --filter @familysync/api build` (produces dist/index.js — Pitfall 4).
5. Start API as a background process with DEV_AUTH_BYPASS INLINE:
`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` (Pitfall 8). NODE_ENV must be `development` (not production — global-setup refuses; not test — dev-bypass activation checks development per 08-RESEARCH note).
6. Wait for API :3000: a curl retry loop `until curl -sf http://localhost:3000/health` with a ~60s deadline; on timeout, `kill $(cat /tmp/api.pid)` and `exit 1`. This step-level wait (D-02) ensures the API is up BEFORE Playwright starts Vite — separate from and earlier than global-setup's own poll.
Do NOT modify playwright.config.ts, global-setup.ts, vite.config.ts, or any spec — CI owns bring-up only (D-01/D-02; phase boundary).
<threat_model>
Trust Boundaries
| Boundary | Description |
|---|---|
| DEV_AUTH_BYPASS in CI | Bypass auth flag active in the harness job only; must never reach the publish job |
| CI test DB → seed | global-setup TRUNCATEs tables; fail-closed guards protect against prod DB |
STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|---|---|---|---|---|
| T-08-06 | Spoofing | DEV_AUTH_BYPASS=true in harness job | mitigate | Bypass is set ONLY in the harness job env, against throwaway DB creds; it never appears in the publish job (Plan 04). global-setup.ts fails closed on NODE_ENV=production and on missing DEV_AUTH_BYPASS, so it cannot wipe/seed an unconfirmed DB (08-RESEARCH Security Domain). |
| T-08-07 | Tampering | drizzle migrate against CI DB | mitigate | db:migrate only; db:push forbidden (grep gate). Throwaway creds, ephemeral container. |
| T-08-08 | Denial of Service | dev-server startup race | mitigate | Explicit :3000/health curl loop before Playwright (D-02) on top of global-setup's :5173/health + /api/me gates; MariaDB healthcheck.sh readiness loop before migrate (Pitfall 11). |
| </threat_model> |
<success_criteria>
- CI-01 (harness half): PR to main brings up API + PWA dev servers + MariaDB with DEV_AUTH_BYPASS and runs the Phase 7 specs headlessly; failure gates merge (ROADMAP criterion 3).
- Readiness: waits for both :3000 and :5173 before Playwright (ROADMAP criterion 4; Pitfall dev-stack races).
- Phase 7 specs reused UNCHANGED (phase boundary); both device profiles run (D-05); traces upload on failure (D-06). </success_criteria>