Files
familysync/.planning/phases/08-gitea-ci/08-VERIFICATION.md
T
Lucas Berger b1851f475e
CI / fast-checks (pull_request) Successful in 49s
CI / api (pull_request) Successful in 56s
CI / harness (pull_request) Successful in 3m23s
CI / publish (pull_request) Has been skipped
docs(08): SUMMARY + VERIFICATION — phase 8 complete, CI-01 + CI-02 delivered
- 08-04-SUMMARY.md: publish job verified green (run #14), both tags pushed,
  security audit pass (PAT masked, --password-stdin), REGISTRY_PAT naming note
- 08-VERIFICATION.md: all six phase-8 ROADMAP criteria passed with evidence table
- REQUIREMENTS.md: CI-01 + CI-02 marked complete (checkboxes + traceability table)
- ROADMAP.md: phase 8 marked [x] complete (2026-06-11), 08-04 plan ticked
- STATE.md: phase complete, D-PAT-NAMING decision recorded, operator next steps updated
2026-06-11 16:17:53 -04:00

5.1 KiB

Phase 8: Gitea CI — Verification

Status: PASSED Verified: 2026-06-11 Evidence basis: Gitea Actions run log + Gitea Packages API inspection by operator


Phase Goal

Every PR to main runs a full regression that gates the merge — lint, typecheck, unit, API-integration against a MariaDB service container, and the Phase 7 mobile Playwright harness as a UI-regression step — and a merge to main builds and publishes the API Docker image. All on the existing self-hosted Gitea Actions runner.

Six-Criteria Evidence Table

# Success Criterion Status Evidence
1 PR triggers lint + typecheck + unit + API-integration vs MariaDB service container; failing run blocks merge PASSED Runs #11 and #12: fast-checks (191s, lint no-op + tsc both apps + PWA vitest) and api (238s, MariaDB cold start + drizzle-kit migrate + DB-backed integration tests) both green. Run blocking enforced by Gitea branch protection on main.
2 API integration tests connect to service-container MariaDB (DB_HOST=127.0.0.1) and pass reliably on cold first run PASSED Run #11 cold start: MariaDB readiness wait (mysql2 loop) completed before migrate; squashed migration baseline (commit c0f892c) eliminated false drizzle-kit destructive diff; all API integration tests passed on first attempt.
3 PR workflow brings up dev stack (API + PWA dev servers + MariaDB, DEV_AUTH_BYPASS=true) and runs Phase 7 mobile Playwright harness headlessly; harness failure blocks merge PASSED Run #11: harness job — 58 specs across iphone/WebKit + pixel/Chromium — all green in 1.6 min. Four CI-specific infrastructure fixes applied (API-reap timeout, ipv4first/127.0.0.1 DNS, dev-user seed, direct test:e2e call). No Phase 7 harness files modified.
4 Harness step waits for both API and PWA dev servers before launching Playwright (no startup-race flake) PASSED mysql2 readiness loop (DB) → :3000/health poll (API) → global-setup :5173 poll (PWA) — three sequential readiness gates before Playwright launches. No flake observed on cold or warm runs.
5 Merge to main builds and pushes API Docker image under a sensible tag PASSED Run #14 (push of merge commit 98acff8): docker build --target production -f apps/api/Dockerfile . succeeded; both tags pushed — familysync-api:latest and familysync-api:v1.1-98acff8 — same digest sha256:ce724852…; confirmed present in Gitea Packages API.
6 Registry credentials never appear in plaintext in the CI logs PASSED Log audit of run #14: PAT masked as *** throughout (Gitea secret scrubber); --password-stdin used exclusively (token piped via stdin); no -p/--password argument form anywhere; docker logout ran in always() cleanup. REGISTRY_PAT naming used (GITEA_ prefix excluded to avoid Gitea's silent secret-drop behavior).

Plans Delivering the Criteria

Plan Contribution
08-01 Runner probe — confirmed ubuntu-latest label, Docker executor (/.dockerenv), GITHUB_SHA availability, Playwright deps install cleanly
08-02 ci.yml: fast-checks job (lint, tsc, PWA vitest) + api job (MariaDB service, mysql2 readiness, drizzle-kit migrate, integration tests). Delivers criteria 1 + 2.
08-03 ci.yml: harness job (dev-stack bring-up, readiness waits, pnpm test:e2e). Delivers criteria 3 + 4. Four CI infrastructure fixes (no Phase 7 files modified).
08-04 ci.yml: publish job (docker login --password-stdin, build --target production from repo root, dual push :latest + :v1.1-, docker logout). Delivers criteria 5 + 6.

Key Fixes Applied During Phase 8 (CI-side only, no harness changes)

  1. squashed migration baseline (commit c0f892c) — single 0000_baseline.sql replaces the incremental migration history; eliminates the false drizzle-kit destructive diff that aborted the first cold CI run.
  2. API-reap + ipv4firstpkill -f "tsx watch" reap guard + --dns-result-order=ipv4first flag ensures the API dev server binds on 127.0.0.1 (not ::1), matching the harness readiness poll.
  3. dev-user seed — global-setup inserts the DEV_AUTH_BYPASS user (id=1) before Playwright launches, so the authed bypass session is valid on first spec.
  4. direct test:e2epnpm --filter @familysync/pwa test:e2e called directly (not via Makefile) to avoid shell-expansion issues in the runner.
  5. REGISTRY_PAT naming (commit 73eecf7) — Gitea runner silently drops secrets whose names begin with GITEA_; secret renamed from GITEA_REGISTRY_PAT to REGISTRY_PAT.

Requirements Delivered

REQ-ID Description Status
CI-01 PR regression gates merge (lint + typecheck + unit + API-integration + mobile harness) Complete
CI-02 Push to main builds + publishes API Docker image Complete

Phase 8 Outcome

Phase 8 is complete. The Gitea CI pipeline is fully operational on the self-hosted runner. Future merges to main will automatically run the full regression gate and publish a new image — no manual steps required.