|
|
|
@@ -0,0 +1,144 @@
|
|
|
|
|
---
|
|
|
|
|
phase: 08-gitea-ci
|
|
|
|
|
plan: 02
|
|
|
|
|
subsystem: infra
|
|
|
|
|
tags: [gitea-actions, ci, mariadb, vitest, drizzle, pnpm, playwright]
|
|
|
|
|
|
|
|
|
|
# Dependency graph
|
|
|
|
|
requires:
|
|
|
|
|
- phase: 08-01
|
|
|
|
|
provides: runner-mode probe answers (Docker-executor, ubuntu-latest, cache-skip, no mysql CLI)
|
|
|
|
|
provides:
|
|
|
|
|
- PR-gating fast-checks job (lint + typecheck + PWA unit tests)
|
|
|
|
|
- PR-gating api job (MariaDB 11 service container + drizzle-kit migrate + 238 API tests)
|
|
|
|
|
- Single CI workflow file .gitea/workflows/ci.yml
|
|
|
|
|
affects: [08-03, 08-04, phase-09, phase-10, phase-11, phase-12]
|
|
|
|
|
|
|
|
|
|
# Tech tracking
|
|
|
|
|
tech-stack:
|
|
|
|
|
added: []
|
|
|
|
|
patterns:
|
|
|
|
|
- "Docker-executor services: mariadb (not docker-run) — confirmed by 08-01 probe"
|
|
|
|
|
- "Node mysql2 poll for MariaDB readiness (no mysql CLI in runner image)"
|
|
|
|
|
- "drizzle-kit migrate (never db:push) on single squashed baseline migration"
|
|
|
|
|
- "pnpm -r --if-present lint as auto-gate (exits 0 until a package lint script lands)"
|
|
|
|
|
|
|
|
|
|
key-files:
|
|
|
|
|
created:
|
|
|
|
|
- .gitea/workflows/ci.yml
|
|
|
|
|
- apps/api/src/db/migrations/0000_baseline.sql
|
|
|
|
|
modified:
|
|
|
|
|
- package.json
|
|
|
|
|
|
|
|
|
|
key-decisions:
|
|
|
|
|
- "D-PROBE-01/02 honored: runs-on ubuntu-latest (not self-hosted), DB_HOST=mariadb (Docker-executor services:)"
|
|
|
|
|
- "Cache DISABLED — actions/cache@v4 timed out in 08-01 probe (D-PROBE-04)"
|
|
|
|
|
- "Readiness: Node mysql2 poll (90s deadline) — no mysql CLI available in runner image (D-PROBE-03)"
|
|
|
|
|
- "Migration squash: all migrations collapsed to 0000_baseline.sql to fix broken cold drizzle-kit migrate"
|
|
|
|
|
- "Lint is a documented no-op placeholder; root script changed to pnpm -r --if-present lint; real ESLint deferred to BACKLOG 999.16"
|
|
|
|
|
|
|
|
|
|
patterns-established:
|
|
|
|
|
- "PR-gate pattern: parallel fast-checks (no DB) + api (MariaDB services:) jobs both gated on pull_request"
|
|
|
|
|
- "Readiness poll pattern: Node mysql2 script with 90s deadline before drizzle-kit migrate"
|
|
|
|
|
|
|
|
|
|
requirements-completed: [CI-01]
|
|
|
|
|
|
|
|
|
|
# Metrics
|
|
|
|
|
duration: ~90min (including squash fix, PR push, and cold-run verification)
|
|
|
|
|
completed: 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.yml` with parallel `fast-checks` and `api` jobs triggered on `pull_request → main`
|
|
|
|
|
- `fast-checks` job: Node 22 + pnpm via corepack, lint (no-op gate), tsc typecheck (both apps including pwa tsconfig.e2e.json), 191/191 PWA unit tests green
|
|
|
|
|
- `api` job: MariaDB 11 via `services:` (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 migrate` by squashing all migrations to a single `0000_baseline.sql` (deviation, see below)
|
|
|
|
|
- Fixed root lint script from `pnpm -r lint` → `pnpm -r --if-present lint` so 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
|
|
|
|
|
|
|
|
|
|
1. **Task 1: Create ci.yml with the fast-checks job** - `667f017` (feat)
|
|
|
|
|
2. **Task 2: Add the API job (MariaDB service + migrate + DB-backed tests)** - `3343f36` (feat)
|
|
|
|
|
3. **Task 3 (out-of-plan deviation — migration squash)** - `c0f892c` (fix)
|
|
|
|
|
4. **Task 3 (out-of-plan deviation — lint fix)** - `dc31d4e` (fix)
|
|
|
|
|
5. **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 parallel
|
|
|
|
|
- `apps/api/src/db/migrations/0000_baseline.sql` — Squashed baseline migration (replaces multiple fragmented migrations)
|
|
|
|
|
- `package.json` — Root `lint` script changed from `pnpm -r lint` to `pnpm -r --if-present lint`
|
|
|
|
|
|
|
|
|
|
## Decisions Made
|
|
|
|
|
|
|
|
|
|
- **runs-on: ubuntu-latest** — plan text said `self-hosted` but 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:11` with `DB_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 `mysql` CLI in runner image (D-PROBE-03), and `mysqladmin ping` was removed in MariaDB 11. Used a Node.js script that polls `mysql2.createConnection().query('SELECT 1')` with a 90s deadline.
|
|
|
|
|
- **Migration squash** — cold `drizzle-kit migrate` failed because 0001_lists_schema recreated tables already created in 0000 (duplicates lists/list_shares/list_items + calendars unique constraint). Squashed to a single `0000_baseline.sql` generated 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 migrate` failed with "table already exists" — migration 0001_lists_schema recreated `lists`, `list_shares`, `list_items`, and the `calendars` unique-constraint that migration 0000 had already created. An orphaned migration `0001_calendars_user_url_unique` also existed. Cold migration was impossible on a fresh DB.
|
|
|
|
|
- **Fix:** Squashed all migrations into a single `apps/api/src/db/migrations/0000_baseline.sql` regenerated from `schema.ts` via `drizzle-kit generate`. Verified: fresh `db:migrate` succeeds, schema is structurally identical to dev DB, `drizzle-kit generate` reports 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 generate` reports 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 lint` emits `ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT` and exits non-zero when no package has a `lint` script. This would immediately block the CI gate even though ESLint is not yet wired.
|
|
|
|
|
- **Fix:** Changed root `package.json` lint script from `pnpm -r lint` to `pnpm -r --if-present lint`. The `--if-present` flag 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_initialized` is available in the MariaDB 11 container image but not callable from the step shell in Docker-executor mode without a `docker exec` into the sidecar. Node mysql2 poll was simpler and equivalent.
|
|
|
|
|
- 08-01 probe workflow was left as `push + pull_request`-triggered after CI verification — set to `workflow_dispatch` only (commit `0b148b9`) 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; both `fast-checks` and `api` jobs are green and stable.
|
|
|
|
|
- **Local dev note:** After the migration squash, any local dev DB that was created before `c0f892c` must be rebuilt: `DROP DATABASE familysync; CREATE DATABASE familysync; pnpm --filter @familysync/api db:migrate`.
|
|
|
|
|
- **BACKLOG 999.16:** ESLint wiring is explicitly deferred. The `--if-present` lint gate in ci.yml will auto-activate once any package adds a `lint` script — no ci.yml change needed.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
*Phase: 08-gitea-ci*
|
|
|
|
|
*Completed: 2026-06-11*
|