d63c831d15
Initialize Go module, directory structure, and full SQLite store layer: - 7-table schema (projects, stages, registries, settings, instances, deploys, deploy_logs) with auto-migration - CRUD operations for all entities with proper error handling - ErrNotFound sentinel for distinguishing 404 from 500 in handlers - WAL mode, foreign keys, busy timeout pragmas
5.1 KiB
5.1 KiB
Phase 1: Project Scaffold & SQLite Store
Status: ✅ Complete Parent plan: PLAN.md Domain: backend
Objective
Initialize the Go project, establish the directory structure, and implement the SQLite store with schema, migrations, and CRUD operations for all entities.
Tasks
- Task 1: Initialize Go module (
go mod init), create directory structure per PLAN.md - Task 2: Add core dependencies to go.mod (sqlite, chi, yaml, uuid, cron)
- Task 3: Define SQLite schema — tables for projects, stages, registries, settings, instances, deploys, deploy_logs
- Task 4: Implement store initialization with auto-migration (create tables if not exist)
- Task 5: Implement projects CRUD (Create, GetByID, GetAll, Update, Delete)
- Task 6: Implement stages CRUD (Create, GetByProjectID, Update, Delete)
- Task 7: Implement registries CRUD (Create, GetByID, GetAll, Update, Delete)
- Task 8: Implement settings Get/Update (single-row config pattern)
- Task 9: Implement instances CRUD (Create, GetByStageID, GetByID, Update, Delete, UpdateStatus)
- Task 10: Implement deploys CRUD (Create, GetByProjectID, GetRecent, GetByID) + deploy_logs append
- Task 11: Create
cmd/server/main.goentry point (minimal — just opens DB, defers close)
Files to Modify/Create
go.mod— module definition and dependenciesgo.sum— dependency checksumscmd/server/main.go— entry pointinternal/store/store.go— DB connection, schema, migrationsinternal/store/projects.go— project queriesinternal/store/stages.go— stage queriesinternal/store/registries.go— registry queriesinternal/store/settings.go— settings queriesinternal/store/instances.go— instance queriesinternal/store/deploys.go— deploy history queries
Acceptance Criteria
go mod tidysucceeds- All store CRUD functions are implemented with proper error handling
- Schema covers all entities from the architecture plan
- Entry point compiles (may not fully run until later phases wire everything)
Notes
- Use
modernc.org/sqlitefor CGo-free SQLite - Use
go-chi/chi/v5for routing (will be wired in Phase 8) - Settings table uses a single-row pattern (one row, upsert on update)
- Instance status should be an enum-like string: "running", "stopped", "failed", "removing"
- Deploy status: "pending", "pulling", "starting", "configuring_proxy", "health_checking", "success", "failed", "rolled_back"
Review Checklist
- All tasks completed
- Code follows Go conventions (gofmt, proper error returns)
- No unintended side effects
- Schema is normalized and covers all planned entities
- CRUD functions handle not-found cases properly
Handoff to Next Phase
What was built
- Go module initialized at
github.com/alexei/docker-watcherwith all core dependencies - Full directory structure created:
cmd/server/,internal/store/, plus empty dirs for config, docker, npm, registry, deployer, health, notify, webhook, api, crypto - SQLite store with 7 tables: projects, stages, registries, settings, instances, deploys, deploy_logs
- Auto-migration runs on store initialization (CREATE TABLE IF NOT EXISTS)
- WAL mode, foreign keys, and busy timeout pragmas enabled
- Settings table uses single-row pattern with
INSERT OR IGNOREseed - Models extracted to
internal/store/models.gofor clean separation
Key files
go.mod— module definition with modernc.org/sqlite, chi, yaml, uuid, croncmd/server/main.go— entry point that creates data dir, opens store, defers closeinternal/store/store.go— DB connection, pragmas, schema DDL, migrationinternal/store/models.go— all entity structs (Project, Stage, Registry, Settings, Instance, Deploy, DeployLog)internal/store/projects.go— full CRUDinternal/store/stages.go— full CRUD with bool-to-int conversion for SQLiteinternal/store/registries.go— full CRUDinternal/store/settings.go— Get/Update (single-row upsert)internal/store/instances.go— full CRUD + UpdateStatusinternal/store/deploys.go— Create, GetByID, GetByProjectID, GetRecent, UpdateDeployStatus, SetDeployInstanceID, AppendDeployLog, GetDeployLogs
Conventions established
- UUIDs generated via
github.com/google/uuidon Create operations - Timestamps stored as
datetime('now')defaults in schema,time.Now().UTC().Format("2006-01-02 15:04:05")in Go code - All query errors wrapped with
fmt.Errorfand%wfor unwrapping - Not-found cases return descriptive error strings (not sentinel errors yet — can be refined)
- Boolean fields stored as INTEGER (0/1) in SQLite, converted via
boolToInthelper - JSON-encoded maps stored as TEXT for env and volumes fields
What Phase 2 needs to know
store.New(dbPath)returns a*Storethat is ready to use — no additional init needed- The
settingstable is pre-seeded with a row (id=1) soGetSettingsalways works - Registry
tokenand settingsnpm_passwordare stored as plain text — Phase 2 (Crypto) should add encryption/decryption around these fields go.sumdoes not exist yet — rungo mod tidyafter Go is available to generate it