feat(site): persist site configuration in ConfigMaps #514

Merged
fuzzy merged 1 commit from feat/site-config-persistence into main 2026-08-04 00:38:52 +00:00
Owner

What

Make site registration survive daemon restarts by persisting site state in Kubernetes ConfigMaps:

  • ConfigMapRepository (internal/kubernetes/site_repository.go) implements site.SiteRepository, storing each site as a JSON-encoded ConfigMap named site-<name> with a thwap.pagesd/site=true label for list selection.
  • Create/Get/List/Update/Delete mirror the in-memory repository semantics (ErrExists/ErrNotFound) using the kubernetes clientset.
  • main.go wires kubernetes.NewSiteRepository(kubeClient, namespace) in place of the memory repository.

Why

Phase 7 task #96 — replaces the ephemeral in-memory site store so registrations persist across restarts.

Testing

  • go build ./...
  • go vet ./...
  • go test -race ./... — 8 new fake-clientset tests (create/get roundtrip, duplicate, missing resources, list, update, delete); full suite passes
  • gofmt -l ./cmd ./internal ./pkg clean
  • golangci-lint run — 0 issues
  • pre-commit hooks all pass

Breaking Changes

None.

Notes

  • The MemoryRepository remains for tests; main now uses the ConfigMap-backed repository.
  • Deployment and audit persistence are out of scope for this task (audit surfaces in the observability task).
  • Issues #94–#96 were closed via the Forgejo API as part of this task per the workflow.

Closes #94
Closes #95
Closes #96

## What Make site registration survive daemon restarts by persisting site state in Kubernetes ConfigMaps: - **`ConfigMapRepository`** (`internal/kubernetes/site_repository.go`) implements `site.SiteRepository`, storing each site as a JSON-encoded ConfigMap named `site-<name>` with a `thwap.pagesd/site=true` label for list selection. - `Create`/`Get`/`List`/`Update`/`Delete` mirror the in-memory repository semantics (`ErrExists`/`ErrNotFound`) using the kubernetes clientset. - `main.go` wires `kubernetes.NewSiteRepository(kubeClient, namespace)` in place of the memory repository. ## Why Phase 7 task #96 — replaces the ephemeral in-memory site store so registrations persist across restarts. ## Testing - [x] `go build ./...` - [x] `go vet ./...` - [x] `go test -race ./...` — 8 new fake-clientset tests (create/get roundtrip, duplicate, missing resources, list, update, delete); full suite passes - [x] `gofmt -l ./cmd ./internal ./pkg` clean - [x] `golangci-lint run` — 0 issues - [x] pre-commit hooks all pass ## Breaking Changes None. ## Notes - The `MemoryRepository` remains for tests; `main` now uses the ConfigMap-backed repository. - Deployment and audit persistence are out of scope for this task (audit surfaces in the observability task). - Issues #94–#96 were closed via the Forgejo API as part of this task per the workflow. Closes #94 Closes #95 Closes #96
feat(site): persist site configuration in ConfigMaps
All checks were successful
Test and Release / lint (pull_request) Successful in 6m56s
Test and Release / test (pull_request) Successful in 7m8s
cc09079322
Replace the in-memory site repository with a ConfigMap-backed
implementation so site registrations survive daemon restarts:

- ConfigMapRepository implements site.SiteRepository, storing each
  site as a JSON-encoded ConfigMap named site-<name> with a
  thwap.pagesd/site=true label for list selection
- Create/Get/List/Update/Delete mirror the in-memory repository
  semantics (ErrExists/ErrNotFound) using the kubernetes clientset
- main wires the ConfigMap repository in place of the memory one

Add fake-clientset tests covering create/get, duplicates, missing
resources, list, update, and delete. Mark task done in ROADMAP.md.

closes #94
closes #95
closes #96
fuzzy scheduled this pull request to auto merge when all checks succeed 2026-08-04 00:32:52 +00:00
the.auditor left a comment

Review Summary

Verified locally on the PR head (cc09079): go build, go vet, gofmt, golangci-lint run all clean; all 8 new ConfigMap-repository tests plus the full suite pass with -race.

Solid implementation. ConfigMapRepository faithfully mirrors the SiteRepository semantics (ErrExists/ErrNotFound), stores each site as JSON under site-<name> with a thwap.pagesd/site=true label for list selection, and Update correctly reuses the fetched object's ResourceVersion. The name prefix (site-) can't collide with the per-site nginx ConfigMaps (named <name>), and site-name length limits keep ConfigMap names within DNS-1123 bounds. main.go wiring is a one-line swap, leaving the memory repo for tests. Fake-clientset test coverage is good (roundtrip, duplicate, missing, list, update, delete).

No blocking issues.

Non-blocking observations:

  1. Create's existence check is Get-then-Create (non-atomic) — concurrent duplicate registration could surface as a raw AlreadyExists API error instead of ErrExists in the race window. Fine for the single-instance daemon; worth noting if the API ever scales out.
  2. Create proceeds past a non-notfound Get error (e.g. transient RBAC/API error) rather than aborting — it would then surface the error on Create. Harmless today, slightly surprising error path.
  3. Deployment and audit persistence remain in-memory (scoped out here) — a restart loses deployment history and audit events even though site registration now survives. Expected per the roadmap split.

Approving.

## Review Summary Verified locally on the PR head (`cc09079`): `go build`, `go vet`, `gofmt`, `golangci-lint run` all clean; all 8 new ConfigMap-repository tests plus the full suite pass with `-race`. Solid implementation. `ConfigMapRepository` faithfully mirrors the `SiteRepository` semantics (`ErrExists`/`ErrNotFound`), stores each site as JSON under `site-<name>` with a `thwap.pagesd/site=true` label for list selection, and `Update` correctly reuses the fetched object's `ResourceVersion`. The name prefix (`site-`) can't collide with the per-site nginx ConfigMaps (named `<name>`), and site-name length limits keep ConfigMap names within DNS-1123 bounds. `main.go` wiring is a one-line swap, leaving the memory repo for tests. Fake-clientset test coverage is good (roundtrip, duplicate, missing, list, update, delete). **No blocking issues.** Non-blocking observations: 1. `Create`'s existence check is `Get`-then-`Create` (non-atomic) — concurrent duplicate registration could surface as a raw `AlreadyExists` API error instead of `ErrExists` in the race window. Fine for the single-instance daemon; worth noting if the API ever scales out. 2. `Create` proceeds past a *non*-notfound `Get` error (e.g. transient RBAC/API error) rather than aborting — it would then surface the error on `Create`. Harmless today, slightly surprising error path. 3. Deployment and audit persistence remain in-memory (scoped out here) — a restart loses deployment history and audit events even though site registration now survives. Expected per the roadmap split. Approving.
fuzzy merged commit cc09079322 into main 2026-08-04 00:38:52 +00:00
fuzzy deleted branch feat/site-config-persistence 2026-08-04 00:38:52 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
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
thwap/thwap-pagesd!514
No description provided.