Phase 1: Service scaffold + deploy #1

Closed
opened 2026-03-22 09:38:24 +00:00 by forgejo_admin · 0 comments

Type

Feature

Lineage

plan-pal-e-mail → Phase 1

Repo

forgejo_admin/pal-e-mail (primary), forgejo_admin/pal-e-services (terraform), forgejo_admin/pal-e-deployments (kustomize)

User Story

As a platform operator
I want an empty pal-e-mail FastAPI service deployed in the cluster
So that Phase 2 can add the send API on a running, healthy foundation

Context

pal-e-mail is a new platform-tier service that centralizes all email sending. This phase creates the empty shell: FastAPI app with /healthz, Postgres for email_log, Gmail OAuth PVC (writable — fixing the read-only secret mount that broke token refresh in basketball-api), Woodpecker CI pipeline, and ArgoCD deployment via kustomize overlay.

Key decisions: internal only (no Tailscale funnel — funnel = false), own Postgres in namespace, writable PVC for Gmail tokens, port 8000, gmail-sdk-ldraney from Forgejo PyPI.

File Targets

Files to create in pal-e-mail:

  • pyproject.toml — FastAPI, SQLAlchemy, alembic, gmail-sdk-ldraney, ruff dev deps
  • src/pal_e_mail/__init__.py — package init
  • src/pal_e_mail/main.py — FastAPI app with /healthz
  • src/pal_e_mail/config.py — settings (DATABASE_URL, GMAIL_SECRETS_DIR)
  • src/pal_e_mail/models.py — EmailLog model (SQLAlchemy)
  • src/pal_e_mail/database.py — engine + session setup
  • Dockerfile — 3-stage (base, builder, runtime), Forgejo PyPI extra-index-url
  • .woodpecker.yaml — test + build-and-push via kaniko
  • alembic.ini + alembic/ — migration setup
  • alembic/versions/001_email_log.py — initial migration
  • tests/test_healthz.py — healthz smoke test

Files to modify in pal-e-services:

  • terraform/k3s.tfvars — add pal-e-mail to services map

Files to create in pal-e-deployments:

  • overlays/pal-e-mail/prod/kustomization.yaml — standard base + patches
  • overlays/pal-e-mail/prod/deployment-patch.yaml — env vars, PVC mounts
  • overlays/pal-e-mail/prod/postgres.yaml — Postgres deployment + PVC + service
  • overlays/pal-e-mail/prod/pvc.yaml — gmail-oauth PVC (writable)

Acceptance Criteria

  • Woodpecker pipeline passes (test + build-and-push)
  • ArgoCD syncs, pod reaches Running state
  • /healthz returns 200 from within cluster (kubectl exec)
  • Postgres connected, alembic migration creates email_log table
  • Gmail OAuth PVC mounted writable at /secrets/gmail
  • kubectl logs shows clean startup, no crash loops

Test Expectations

  • Unit test: test_healthz.py — GET /healthz returns 200 with {"status": "ok"}
  • Run command: pytest tests/

Constraints

  • Follow existing patterns: basketball-api Dockerfile (3-stage), mcd-tracker kustomize overlay
  • Forgejo PyPI for gmail-sdk: --extra-index-url https://forgejo.tail5b443a.ts.net/api/packages/forgejo_admin/pypi/simple/
  • Port 8000 everywhere (Dockerfile EXPOSE, k3s.tfvars, kustomize, probes)
  • Harbor registry path: pal-e-mail/api
  • No Keycloak — internal service, no auth
  • funnel = false in k3s.tfvars

Checklist

  • PR opened (pal-e-mail repo — initial scaffold)
  • PR opened (pal-e-services — terraform)
  • PR opened (pal-e-deployments — kustomize)
  • Tests pass
  • No unrelated changes
  • plan-pal-e-mail — parent plan
  • service-onboarding-sop — deployment procedure
  • convention-kustomize-overlay — overlay pattern
### Type Feature ### Lineage `plan-pal-e-mail` → Phase 1 ### Repo `forgejo_admin/pal-e-mail` (primary), `forgejo_admin/pal-e-services` (terraform), `forgejo_admin/pal-e-deployments` (kustomize) ### User Story As a platform operator I want an empty pal-e-mail FastAPI service deployed in the cluster So that Phase 2 can add the send API on a running, healthy foundation ### Context pal-e-mail is a new platform-tier service that centralizes all email sending. This phase creates the empty shell: FastAPI app with `/healthz`, Postgres for email_log, Gmail OAuth PVC (writable — fixing the read-only secret mount that broke token refresh in basketball-api), Woodpecker CI pipeline, and ArgoCD deployment via kustomize overlay. Key decisions: internal only (no Tailscale funnel — `funnel = false`), own Postgres in namespace, writable PVC for Gmail tokens, port 8000, gmail-sdk-ldraney from Forgejo PyPI. ### File Targets Files to create in `pal-e-mail`: - `pyproject.toml` — FastAPI, SQLAlchemy, alembic, gmail-sdk-ldraney, ruff dev deps - `src/pal_e_mail/__init__.py` — package init - `src/pal_e_mail/main.py` — FastAPI app with /healthz - `src/pal_e_mail/config.py` — settings (DATABASE_URL, GMAIL_SECRETS_DIR) - `src/pal_e_mail/models.py` — EmailLog model (SQLAlchemy) - `src/pal_e_mail/database.py` — engine + session setup - `Dockerfile` — 3-stage (base, builder, runtime), Forgejo PyPI extra-index-url - `.woodpecker.yaml` — test + build-and-push via kaniko - `alembic.ini` + `alembic/` — migration setup - `alembic/versions/001_email_log.py` — initial migration - `tests/test_healthz.py` — healthz smoke test Files to modify in `pal-e-services`: - `terraform/k3s.tfvars` — add pal-e-mail to services map Files to create in `pal-e-deployments`: - `overlays/pal-e-mail/prod/kustomization.yaml` — standard base + patches - `overlays/pal-e-mail/prod/deployment-patch.yaml` — env vars, PVC mounts - `overlays/pal-e-mail/prod/postgres.yaml` — Postgres deployment + PVC + service - `overlays/pal-e-mail/prod/pvc.yaml` — gmail-oauth PVC (writable) ### Acceptance Criteria - [ ] Woodpecker pipeline passes (test + build-and-push) - [ ] ArgoCD syncs, pod reaches Running state - [ ] `/healthz` returns 200 from within cluster (`kubectl exec`) - [ ] Postgres connected, alembic migration creates email_log table - [ ] Gmail OAuth PVC mounted writable at `/secrets/gmail` - [ ] `kubectl logs` shows clean startup, no crash loops ### Test Expectations - [ ] Unit test: `test_healthz.py` — GET /healthz returns 200 with `{"status": "ok"}` - Run command: `pytest tests/` ### Constraints - Follow existing patterns: basketball-api Dockerfile (3-stage), mcd-tracker kustomize overlay - Forgejo PyPI for gmail-sdk: `--extra-index-url https://forgejo.tail5b443a.ts.net/api/packages/forgejo_admin/pypi/simple/` - Port 8000 everywhere (Dockerfile EXPOSE, k3s.tfvars, kustomize, probes) - Harbor registry path: `pal-e-mail/api` - No Keycloak — internal service, no auth - `funnel = false` in k3s.tfvars ### Checklist - [ ] PR opened (pal-e-mail repo — initial scaffold) - [ ] PR opened (pal-e-services — terraform) - [ ] PR opened (pal-e-deployments — kustomize) - [ ] Tests pass - [ ] No unrelated changes ### Related - `plan-pal-e-mail` — parent plan - `service-onboarding-sop` — deployment procedure - `convention-kustomize-overlay` — overlay pattern
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/pal-e-mail#1
No description provided.