You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 07bc8d0
Browse filesBrowse the repository at this point in the historyBrowse files
@@ -64,19 +64,23 @@ codeforphilly-data ─── Public data store. Branches:
64
64
│ merge target). Hot-reload webhook
65
65
│ fires on push.
66
66
│
67
-
cfp-sandbox-cluster ─── GitOps repo (hologit-projected) that pulls
68
-
│ this repo's `deploy/kustomize/` upstream
69
-
│ and applies it via Kustomize. See
67
+
cfp-sandbox-cluster ─── GitOps repos (hologit-projected) that pin a
68
+
cfp-live-cluster │ release tag of this repo, project its
69
+
│ `deploy/kustomize/base/` and apply it via
70
+
│ Kustomize. Sandbox = next-v2.codeforphilly.org
71
+
│ (ns codeforphilly-rewrite-sandbox); prod =
72
+
│ next.codeforphilly.org → codeforphilly.org at
73
+
│ cutover (ns codeforphilly-ng). See
70
74
│ `docs/operations/deploy.md`.
71
75
```
72
76
73
-
Operator docs in [`docs/operations/`](../docs/operations/): `deploy.md` for the cluster topology, `sandbox-deploy.md` for the manual procedure, `runbook.md` for incident response (including the hot-reload webhook).
77
+
Operator docs in [`docs/operations/`](../docs/operations/): `deploy.md` for the cluster topology + GitOps flow, `releases.md` for cutting a release, `sandbox-deploy.md` for the sandbox specifics, `runbook.md` for incident response (including the hot-reload webhook), `cutover.md` for the production hostname move.
-**Public storage** — [gitsheets](https://github.com/JarvusInnovations/gitsheets) (TOML records in a git repo). Public-by-design — civic transparency. No persistent OLTP. See [specs/behaviors/storage.md](../specs/behaviors/storage.md).
79
-
-**Private storage** — S3-compatible bucket holding `.jsonl` files (private profiles + legacy password hashes). Boot-load + in-memory; PUT on mutation. See [specs/behaviors/private-storage.md](../specs/behaviors/private-storage.md). Real production private data never lands on a dev machine.
83
+
-**Private storage** — `.jsonl` files (private profiles + legacy password hashes) on a filesystem PVC in every deployed environment (`STORAGE_BACKEND=filesystem`); an S3-compatible backend exists but is unused. Boot-load + in-memory; rewrite on mutation. See [specs/behaviors/private-storage.md](../specs/behaviors/private-storage.md). Real production private data never lands on a dev machine.
80
84
-**Schemas** — Zod in `packages/shared`, consumed by both web and api, validating records in both stores.
81
85
-**Full-text search** — in-memory SQLite FTS5 (or MiniSearch fallback), rebuilt at boot from gitsheets state.
82
86
-**Auth** — GitHub OAuth as the sole primary identity provider; stateless JWT sessions. We're also the SAML IdP for codeforphilly.slack.com. See [specs/api/auth.md](../specs/api/auth.md), [specs/api/saml.md](../specs/api/saml.md).
@@ -135,23 +139,24 @@ npm run -w apps/web dev # web only
135
139
136
140
## Deploying
137
141
138
-
GitOps. This repo publishes a Docker image to GHCR; the [`cfp-sandbox-cluster`](https://github.com/CodeForPhilly/cfp-sandbox-cluster)repo pulls our [`deploy/kustomize/`](../deploy/kustomize/) upstream via hologit and applies it with Kustomize. Production will follow the same pattern under a `cfp-prod-cluster` repo.
142
+
GitOps. Releases publish a Docker image to GHCR; two cluster repos — [`cfp-sandbox-cluster`](https://github.com/CodeForPhilly/cfp-sandbox-cluster)(sandbox) and [`cfp-live-cluster`](https://github.com/CodeForPhilly/cfp-live-cluster) (production, alongside legacy laddr) — each pin a release tag, project our [`deploy/kustomize/base/`](../deploy/kustomize/base/)via hologit and apply it with Kustomize.
139
143
140
144
Typical change flow:
141
145
142
-
1.**Merge to `main`** — CI builds + tests; nothing deploys yet.
143
-
2.**Publish image**(currently manual) — `docker build --platform=linux/amd64 -t ghcr.io/codeforphilly/codeforphilly-ng:sandbox . && docker push …`. Apple-silicon dev machines must set the platform flag — cluster nodes are amd64.
144
-
3.**GitOps pickup** — `cfp-sandbox-cluster` projects from our `deploy/kustomize/`; on its own merge, applies via `kubectl apply -k`.
146
+
1.**Merge to `develop`** — CI builds + tests; pushing `develop` opens/updates a `Release: vX.Y.Z` PR into `main` (see `docs/operations/releases.md` and the `release-flow` skill).
147
+
2.**Publish image**— merging the Release PR tags `vX.Y.Z`; `container-publish.yml` builds and pushes `ghcr.io/codeforphilly/codeforphilly-ng:vX.Y.Z` (+ `:latest`). No manual `docker push`.
148
+
3.**GitOps pickup** — in the cluster repo, bump `.holo/sources/codeforphilly-ng.toml` (`ref = "refs/tags/vX.Y.Z"`) and `images[].newTag` in `codeforphilly-ng/app/kustomization.yaml` together; merge to `main`; "Build k8s-manifests" projects to `releases/k8s-manifests`; a bot PR into `deploys/k8s-manifests` applies on merge. Sandbox first, then live.
145
149
4.**Pod boot** — single replica, `Recreate` strategy. Container entrypoint bare-clones the data repo on every pod start (the data volume is `emptyDir`, so first boot = every fresh pod). Node boots: env → store load → **reconcile** (ff/replay/escape-hatch against `origin/<CFP_DATA_BRANCH>`) → **push daemon** → routes → SPA. `/api/health/ready` returns 200 once stores are loaded *and* reconciled.
146
150
5.**Live data updates** — independent of app deploy. Pushes to `published` trigger the [hot-reload webhook](../docs/operations/runbook.md#hot-reload-webhook); the pod rebuilds in-memory state in place, no restart.
147
151
148
152
Constraints worth knowing before touching anything deploy-shaped:
149
153
150
154
-**Single replica is non-negotiable** — writes flow through an in-process mutex; horizontal scale would lose write serialization.
151
155
-**One image for API + SPA** — Fastify serves the built `apps/web/dist` as fallthrough. No separate web container.
152
-
-**Sealed secrets are cluster-bound** — sandbox-sealed secrets can't decrypt in prod. Plain values live in `.env` locally; cluster values live in the sandbox-cluster repo's `codeforphilly-ng.secrets/`.
156
+
-**Sealed secrets are cluster-bound** — sandbox-sealed secrets can't decrypt in prod. Plain values live in `.env` locally; cluster values live in each cluster repo's `codeforphilly-ng.secrets/`.
157
+
-**Cutover is a hostname move, not a DNS change** — the apex already resolves to the live cluster's gateway; T-0 is one commit in `cfp-live-cluster` moving listeners from `_gateways/code-for-philly.yaml` to `_gateways/codeforphilly-ng.yaml`.
0 commit comments