Files
2026-06-18 22:21:38 -04:00

6.5 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions requirements-completed duration completed
08-gitea-ci 04 infra
gitea
docker
ci
registry
publish
security
phase provides
08-03 harness job in ci.yml; dev-stack bring-up confirmed in CI
publish job in .gitea/workflows/ci.yml (push to main → build + push API Docker image)
familysync-api:latest and familysync-api:v1.1-<7charsha> tags in Gitea registry
--password-stdin docker login pattern (REGISTRY_PAT secret, never plaintext)
phase-09
phase-10
phase-11
phase-12
added patterns
docker login --password-stdin (PAT piped via stdin; -p flag forbidden)
dual-tag publish: :latest + :<milestone>-<shortsha> (D-04 traceability)
docker build from repo root: -f apps/api/Dockerfile . (Dockerfile requires workspace manifest)
docker logout in always() step to drop credential from runner after push
Gitea secret prefix exclusion: REGISTRY_PAT not GITEA_REGISTRY_PAT (Gitea reserves GITEA_ prefix)
created modified
.gitea/workflows/ci.yml
D-PAT-NAMING: Gitea runner silently ignores secrets with the GITEA_ prefix; secret renamed from GITEA_REGISTRY_PAT to REGISTRY_PAT in both the Gitea repo secret and ci.yml (commit 73eecf7). This is the load-bearing fix that unblocked the publish job.
D-SHELL-FORM: Used shell docker login/build/push (not docker/login-action or docker/build-push-action) — matches 08-RESEARCH §Pattern 6 recommendation; simpler and has no marketplace action dependency.
D-DUAL-TAG: Two docker push calls for :latest and :v1.1-<shortsha>; same digest, two tags. Traceability tag links image to the exact merge commit.
D-LOGOUT: docker logout in always() step — drops stored credential from runner regardless of push success/failure (security hygiene).
CI-02
checkpoint-verified 2026-06-11

Phase 08 Plan 04: Publish Job Summary

Publish job wired to push-to-main: API Docker production image pushed to Gitea registry under :latest and :v1.1-<7charsha>, PAT authenticated via --password-stdin (never plaintext), security audit passed — CI-02 delivered.

Performance

  • Duration: multi-step (Task 1 executed, Task 2 was a human-verify checkpoint — verified green on run #14)
  • Started: 2026-06-11
  • Completed: 2026-06-11
  • Tasks: 2 (1 auto + 1 human-verify checkpoint)
  • Files modified: 1

Accomplishments

  • Added the publish job to .gitea/workflows/ci.yml: gated on github.event_name == 'push' && github.ref == 'refs/heads/main', never fires on pull_request.
  • Run #14 (merge commit 98acff8 pushed to main) confirmed SUCCESS (1m): docker login succeeded, both image tags pushed (same digest sha256:ce724852…) — familysync-api:latest and familysync-api:v1.1-98acff8 present in Gitea Packages API.
  • Security audit of the CI log passed: PAT masked as *** throughout (Gitea secret scrubber); --password-stdin used exclusively; no -p/--password form anywhere; docker logout ran in the always() cleanup step. No plaintext token anywhere in the log.
  • Identified and fixed the GITEA*-prefix secret naming bug: Gitea runner silently drops secrets whose names start with GITEA*; renamed secret from GITEA_REGISTRY_PATtoREGISTRY_PAT in both the repo secret and ci.yml (commit 73eecf7).

Task Commits

  1. Task 1: Add the publish job - ebcc38d (feat)
  2. Task 1 fix: REGISTRY_PAT naming - 73eecf7 (fix — GITEA_ prefix exclusion)
  3. Pre-merge cleanup: remove throwaway runner-probe.yml - dcf4242 (chore)
  4. Task 2: Human-verify checkpoint — verified green (run #14); no code commit required

Files Created/Modified

  • .gitea/workflows/ci.yml — publish job added (push-to-main guard, --password-stdin docker login, build --target production from repo root, dual push :latest + :v1.1-, docker logout always())

Decisions Made

  • REGISTRY_PAT naming (D-PAT-NAMING): Gitea reserves the GITEA_ prefix for built-in variables and silently strips any user-defined secret with that prefix from the runner environment. The original plan named the secret GITEA_REGISTRY_PAT; the fix renames it to REGISTRY_PAT (commit 73eecf7). Downstream plans must use REGISTRY_PAT if they add registry operations.
  • Shell form over marketplace actions: echo "${{ secrets.REGISTRY_PAT }}" | docker login ... --password-stdin + docker build + docker push rather than docker/login-action / docker/build-push-action. This matches the 08-RESEARCH §Pattern 6 preferred path; no external action marketplace dependency.
  • Dual push: two separate docker push calls (:latest + :<milestone>-<sha>) — same digest, two references. :latest is the moving pointer; :<milestone>-<sha> is the immutable traceability tag per D-04.

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] GITEA_REGISTRY_PAT secret prefix rejected by Gitea runner

  • Found during: Task 1 → human-verify checkpoint (run #14 initially failed login)
  • Issue: Gitea Actions runner silently ignores secrets with the GITEA_ prefix (reserved namespace). The GITEA_REGISTRY_PAT secret was never injected into the job environment, causing docker login to fail with an empty password.
  • Fix: Renamed the Gitea repo secret from GITEA_REGISTRY_PAT to REGISTRY_PAT and updated the ci.yml reference accordingly (commit 73eecf7).
  • Files modified: .gitea/workflows/ci.yml
  • Verification: Run #14 succeeded — "Login Succeeded" in log; both tags pushed; PAT masked.
  • Committed in: 73eecf7

Total deviations: 1 auto-fixed (Rule 1 - Bug) Impact on plan: Required for the publish job to function at all. No scope creep. Security outcome (no plaintext PAT) unchanged.

Issues Encountered

The GITEA_-prefix restriction was not documented in the plan or research notes; it was discovered empirically when the first publish run failed at docker login. The fix was straightforward once identified. No other issues encountered.

Next Phase Readiness

  • Phase 8 (Gitea CI) is fully complete — all six ROADMAP success criteria met (see 08-VERIFICATION.md).
  • CI-01 (PR regression: lint + typecheck + unit + API integration + mobile harness) delivered by plans 02 + 03.
  • CI-02 (push-to-main publish) delivered by this plan (04).
  • The Gitea registry now has a pullable familysync-api:latest image. Future phases can reference it for deployment documentation or smoke tests.
  • Phase 9 (Faster Write-Back) is fully independent and can start immediately.

Phase: 08-gitea-ci Completed: 2026-06-11