Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9.2 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 | 02 | infra |
|
|
|
|
|
|
|
|
|
~90min (including squash fix, PR push, and cold-run verification) | 2026-06-11 |
Phase 08 Plan 02: PR-Gating CI Jobs Summary
Gitea Actions ci.yml delivers parallel PR-gating fast-checks (191 PWA tests green) and api (MariaDB 11 service container, squashed baseline migration, 238 API tests green) jobs on a cold first run — CI-01 non-harness half complete
Performance
- Duration: ~90 min
- Started: 2026-06-11T15:00:00Z
- Completed: 2026-06-11T~17:00:00Z
- Tasks: 3 (including 1 checkpoint verified by operator)
- Files modified: 3
Accomplishments
- Created
.gitea/workflows/ci.ymlwith parallelfast-checksandapijobs triggered onpull_request → main fast-checksjob: Node 22 + pnpm via corepack, lint (no-op gate), tsc typecheck (both apps including pwa tsconfig.e2e.json), 191/191 PWA unit tests greenapijob: MariaDB 11 viaservices:(Docker-executor confirmed by 08-01), Node mysql2 readiness poll (90s), drizzle-kit migrate, 238/238 API integration tests green — passed cold on first run- Fixed broken cold
drizzle-kit migrateby squashing all migrations to a single0000_baseline.sql(deviation, see below) - Fixed root lint script from
pnpm -r lint→pnpm -r --if-present lintso it exits 0 today and auto-gates once a package lint script lands - Gitea Actions run #5 (PR #3, head
0b148b9): both jobs SUCCESS on a cold pull_request run
Task Commits
- Task 1: Create ci.yml with the fast-checks job -
667f017(feat) - Task 2: Add the API job (MariaDB service + migrate + DB-backed tests) -
3343f36(feat) - Task 3 (out-of-plan deviation — migration squash) -
c0f892c(fix) - Task 3 (out-of-plan deviation — lint fix) -
dc31d4e(fix) - Task 3 (out-of-plan — probe set to manual-only after CI verified) -
0b148b9(chore)
Task 3 was a checkpoint:human-verify; operator confirmed both jobs green on cold run.
Files Created/Modified
.gitea/workflows/ci.yml— PR-gating workflow: fast-checks + api jobs in parallelapps/api/src/db/migrations/0000_baseline.sql— Squashed baseline migration (replaces multiple fragmented migrations)package.json— Rootlintscript changed frompnpm -r linttopnpm -r --if-present lint
Decisions Made
- runs-on: ubuntu-latest — plan text said
self-hostedbut 08-01 probe confirmed the runner has no self-hosted label; ubuntu-latest is the only working value (D-PROBE-01). - services: mariadb (Docker-executor path) — 08-01 confirmed Docker-executor (/.dockerenv present); used
services: mariadb:11withDB_HOST: mariadb, not the host-mode docker-run fallback. - Cache DISABLED — actions/cache@v4 timed out in the 08-01 probe run; omitted entirely (D-PROBE-04).
- Node mysql2 readiness poll — no
mysqlCLI in runner image (D-PROBE-03), andmysqladmin pingwas removed in MariaDB 11. Used a Node.js script that pollsmysql2.createConnection().query('SELECT 1')with a 90s deadline. - Migration squash — cold
drizzle-kit migratefailed because 0001_lists_schema recreated tables already created in 0000 (duplicates lists/list_shares/list_items + calendars unique constraint). Squashed to a single0000_baseline.sqlgenerated from current schema.ts. See Deviations. - Lint no-op gate —
pnpm lint(pnpm -r --if-present lint) exits 0 today (no package defines a lint script). This is intentional: the gate exists structurally and will auto-block once ESLint is wired. Real lint wiring deferred to BACKLOG 999.16 (operator decision).
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Squashed fragmented drizzle-kit migrations to fix broken cold migrate
- Found during: Task 3 (PR cold-run verification)
- Issue: Cold
drizzle-kit migratefailed with "table already exists" — migration 0001_lists_schema recreatedlists,list_shares,list_items, and thecalendarsunique-constraint that migration 0000 had already created. An orphaned migration0001_calendars_user_url_uniquealso existed. Cold migration was impossible on a fresh DB. - Fix: Squashed all migrations into a single
apps/api/src/db/migrations/0000_baseline.sqlregenerated fromschema.tsviadrizzle-kit generate. Verified: freshdb:migratesucceeds, schema is structurally identical to dev DB,drizzle-kit generatereports no drift, 238 API tests pass. Local dev DBs must be rebuilt (drop +db:migrate); no production DB exists. - Files modified:
apps/api/src/db/migrations/0000_baseline.sql, removed orphaned 0001 files - Verification: CI run #5 cold api job passed;
drizzle-kit generatereports no drift post-squash - Committed in:
c0f892c
2. [Rule 1 - Bug] Fixed root lint script to exit 0 on no-script workspaces
- Found during: Task 1/2 (fast-checks job authoring)
- Issue:
pnpm -r lintemitsERR_PNPM_RECURSIVE_RUN_NO_SCRIPTand exits non-zero when no package has alintscript. This would immediately block the CI gate even though ESLint is not yet wired. - Fix: Changed root
package.jsonlint script frompnpm -r linttopnpm -r --if-present lint. The--if-presentflag silently skips packages without the script; exits 0. When any package adds a lint script, it is auto-gated. ESLint wiring deferred to BACKLOG 999.16. - Files modified:
package.json - Verification: CI fast-checks job passes lint step; no ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT in run #5 log
- Committed in:
dc31d4e
Total deviations: 2 auto-fixed (2 Rule 1 bugs) Impact on plan: Both fixes were required for the cold-run pass. No scope creep.
Issues Encountered
- MariaDB 11 does not include
mysqladmin ping(removed upstream) — plan text mentioned it as a readiness option but this is a known pitfall (08-PITFALLS Pitfall 2). Used Node mysql2 poll instead. healthcheck.sh --connect --innodb_initializedis available in the MariaDB 11 container image but not callable from the step shell in Docker-executor mode without adocker execinto the sidecar. Node mysql2 poll was simpler and equivalent.- 08-01 probe workflow was left as
push + pull_request-triggered after CI verification — set toworkflow_dispatchonly (commit0b148b9) to stop redundant re-runs on unrelated PRs.
Threat Surface Scan
No new endpoints, auth paths, file access patterns, or schema changes at trust boundaries introduced in this plan. The ci.yml uses throwaway creds (familysync/testpass, root/root) scoped to ephemeral MariaDB service containers only — T-08-03 mitigated. db:push absent from workflow — T-08-04 mitigated. Node mysql2 readiness poll with 90s deadline — T-08-05 mitigated.
Known Stubs
None — this plan produces CI workflow config only.
Next Phase Readiness
- 08-03 (PWA harness): ci.yml is the target file for Plans 03 and 04. The
push: branches: [main]trigger is already declared in ci.yml for the publish job (Plan 04). Plan 03 adds the harness job; bothfast-checksandapijobs are green and stable. - Local dev note: After the migration squash, any local dev DB that was created before
c0f892cmust be rebuilt:DROP DATABASE familysync; CREATE DATABASE familysync; pnpm --filter @familysync/api db:migrate. - BACKLOG 999.16: ESLint wiring is explicitly deferred. The
--if-presentlint gate in ci.yml will auto-activate once any package adds alintscript — no ci.yml change needed.
Phase: 08-gitea-ci Completed: 2026-06-11