docs(07-01): complete plan summary — embed anchor, RunMigrations, health endpoint split
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bdd3cba314
commit
735106f797
1 changed files with 142 additions and 0 deletions
142
.planning/phases/07-deploy-v1/07-01-SUMMARY.md
Normal file
142
.planning/phases/07-deploy-v1/07-01-SUMMARY.md
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
---
|
||||
phase: 07-deploy-v1
|
||||
plan: "01"
|
||||
subsystem: backend-deploy
|
||||
tags: [go, embed, goose, health-endpoints, deploy]
|
||||
dependency_graph:
|
||||
requires:
|
||||
- 06-02 (cmd/worker wiring — same pool/db patterns mirrored)
|
||||
provides:
|
||||
- embed.FS anchor for static/ and migrations/ (consumed by Dockerfile in plan 07-02)
|
||||
- RunMigrations for use in cmd/web startup (D-10)
|
||||
- /healthz liveness and /readyz readiness endpoints (D-12, D-13)
|
||||
affects:
|
||||
- backend/cmd/web/main.go (startup sequence)
|
||||
- backend/internal/web/router.go (NewRouter signature change)
|
||||
tech_stack:
|
||||
added:
|
||||
- go:embed (stdlib) — static asset and migration embedding
|
||||
- github.com/pressly/goose/v3 — SQL migration runner via embedded FS
|
||||
- github.com/jackc/pgx/v5/stdlib — pgx/v5 database/sql bridge for goose
|
||||
patterns:
|
||||
- embed.FS anchor in package root with //go:embed directives
|
||||
- fs.FS parameter for static serving (replaces string path)
|
||||
- goose.SetBaseFS + goose.Up for idempotent embedded migrations
|
||||
key_files:
|
||||
created:
|
||||
- backend/embed.go
|
||||
- backend/internal/db/migrate.go
|
||||
modified:
|
||||
- backend/internal/web/handlers.go
|
||||
- backend/internal/web/handlers_test.go
|
||||
- backend/internal/web/router.go
|
||||
- backend/cmd/web/main.go
|
||||
- backend/internal/web/csrf_test.go
|
||||
- backend/internal/web/handlers_auth_test.go
|
||||
- backend/internal/web/handlers_files_test.go
|
||||
- backend/internal/web/handlers_tablos_test.go
|
||||
- backend/internal/web/handlers_tasks_test.go
|
||||
decisions:
|
||||
- "embed.go in package assets at backend/ root — module root makes static/ and migrations/ siblings, no ../ paths needed"
|
||||
- "import assets \"backend\" aliased import — package name assets matches package declaration in embed.go"
|
||||
- "pool.Config().ConnConfig.ConnString() for DSN extraction — avoids storing DSN separately"
|
||||
- "goose default table name goose_db_version — no custom table needed (T-07-02 accepted)"
|
||||
- "fs.Sub() strips static/ prefix from embedded FS — avoids double-prefix in served URLs"
|
||||
- "Variable renamed fileHandler (not fs) — prevents shadowing io/fs import in router.go"
|
||||
metrics:
|
||||
duration: "~6 minutes"
|
||||
completed: "2026-05-15"
|
||||
tasks: 2
|
||||
files: 11
|
||||
---
|
||||
|
||||
# Phase 7 Plan 1: Go embed anchor, goose RunMigrations, and /healthz+/readyz handler split Summary
|
||||
|
||||
## What Was Built
|
||||
|
||||
go:embed anchor for zero-runtime-file-dependency binary, goose RunMigrations using pgx/v5/stdlib bridge, and liveness/readiness health endpoint split (HealthzHandler no-arg + ReadyzHandler with pinger).
|
||||
|
||||
## Tasks Completed
|
||||
|
||||
| Task | Name | Commit | Files |
|
||||
|------|------|--------|-------|
|
||||
| 1 | go:embed anchor, goose RunMigrations, handler split | 77e37cb | backend/embed.go, backend/internal/db/migrate.go, backend/internal/web/handlers.go, backend/internal/web/handlers_test.go |
|
||||
| 2 | Wire embed.FS into NewRouter and RunMigrations into main.go | bdd3cba | backend/internal/web/router.go, backend/cmd/web/main.go, 5 test files |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
1. `embed.go` placed at `backend/` root in `package assets` — the module root makes `static/` and `migrations/` natural siblings so `//go:embed` directives resolve without `../` paths. Module is `module backend`; consumers import with `import assets "backend"` which aliases the import path to the package identifier.
|
||||
|
||||
2. `pool.Config().ConnConfig.ConnString()` used to extract DSN for goose's database/sql bridge — avoids threading DSN as a separate parameter through the call stack.
|
||||
|
||||
3. `goose.SetBaseFS` + `goose.Up(sqlDB, "migrations")` — the embedded FS subdirectory path `"migrations"` matches the actual directory name in the module root; no path remapping needed.
|
||||
|
||||
4. `fs.Sub(staticFS, "static")` strips the `static/` prefix from the embedded FS before passing to `http.FileServer(http.FS(...))` — this ensures `/static/tailwind.css` maps to the correct embedded entry without double-prefix.
|
||||
|
||||
5. Local variable renamed `fileHandler` (was `fs`) in `router.go` to prevent shadowing the `"io/fs"` package import.
|
||||
|
||||
6. All 5 test helper files updated from `"./static"` string to `os.DirFS("./static")` to match the new `fs.FS` parameter type in `NewRouter`.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 3 - Blocking] router.go and all *_test.go call sites updated in Task 1**
|
||||
- **Found during:** Task 1 GREEN phase (handlers.go updated but router.go still called HealthzHandler(pinger))
|
||||
- **Issue:** Changing HealthzHandler's signature from `(pinger Pinger)` to `()` caused compilation failure in router.go which prevented the handler tests from compiling at all.
|
||||
- **Fix:** Updated router.go, cmd/web/main.go, and all 5 test helper files as part of the GREEN implementation. These are all interdependent changes that cannot compile in isolation. Task 2 changes were merged into a single GREEN commit after the RED test commit.
|
||||
- **Files modified:** backend/internal/web/router.go, backend/cmd/web/main.go, 5 *_test.go files
|
||||
- **Commit:** bdd3cba
|
||||
|
||||
**2. [Rule 3 - Blocking] Generated files needed in worktree (sqlc + templ)**
|
||||
- **Found during:** First test run in worktree context
|
||||
- **Issue:** The worktree starts clean — sqlc-generated .go files and templ-generated *_templ.go files are gitignored and must be regenerated per DEVELOPMENT.md.
|
||||
- **Fix:** Ran `templ generate` (via `just generate` partial) and `sqlc generate` in the worktree backend directory before running tests.
|
||||
- **Files modified:** None (generated files are gitignored; not committed)
|
||||
|
||||
## Verification
|
||||
|
||||
```
|
||||
cd backend && go test ./... -count=1
|
||||
```
|
||||
|
||||
All packages pass:
|
||||
- `backend/internal/auth` — ok
|
||||
- `backend/internal/db` — ok
|
||||
- `backend/internal/files` — ok
|
||||
- `backend/internal/jobs` — ok
|
||||
- `backend/internal/web` — ok (TestHealthz_OK, TestReadyz_OK, TestReadyz_Down all pass)
|
||||
- `backend/internal/web/ui` — ok
|
||||
- `backend/templates` — ok
|
||||
|
||||
```
|
||||
go build -o /tmp/xtablo-web ./cmd/web && ls -la /tmp/xtablo-web
|
||||
```
|
||||
Binary compiles at ~22.7 MB with embedded assets and migrations.
|
||||
|
||||
## Success Criteria Check
|
||||
|
||||
1. `go test ./... -count=1` exits 0 — PASS
|
||||
2. `go build ./cmd/web/...` exits 0 — PASS
|
||||
3. `grep ReadyzHandler backend/internal/web/router.go` — PASS (r.Get("/readyz", ReadyzHandler(pinger)))
|
||||
4. `grep RunMigrations backend/cmd/web/main.go` — PASS (db.RunMigrations(ctx, pool, assets.Migrations))
|
||||
5. `backend/embed.go` in `package assets` with `//go:embed all:static` and `//go:embed migrations` — PASS
|
||||
6. `backend/internal/db/migrate.go` exports `RunMigrations` — PASS
|
||||
7. TestHealthz_OK passes without pinger; TestHealthz_Down deleted; TestReadyz_OK and TestReadyz_Down pass — PASS
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None.
|
||||
|
||||
## Threat Flags
|
||||
|
||||
No new threat surface introduced beyond plan's threat_model. Health endpoints return only `{"status":"ok"}` or `{"status":"degraded","db":"down"}` — no version strings, stack traces, or DSN fragments (T-07-01 mitigated).
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- backend/embed.go: EXISTS
|
||||
- backend/internal/db/migrate.go: EXISTS
|
||||
- backend/internal/web/handlers.go: EXISTS (contains ReadyzHandler)
|
||||
- backend/internal/web/router.go: EXISTS (contains /readyz route)
|
||||
- backend/cmd/web/main.go: EXISTS (contains RunMigrations call)
|
||||
- Commits 77e37cb and bdd3cba: VERIFIED in git log
|
||||
Loading…
Reference in a new issue