Files
tiny-forge/plans/docker-watcher-core/phase-1-scaffold-store.md
T
alexei.dolgolyov d63c831d15 feat(docker-watcher): phase 1 - project scaffold & SQLite store
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
2026-03-27 20:52:29 +03:00

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.go entry point (minimal — just opens DB, defers close)

Files to Modify/Create

  • go.mod — module definition and dependencies
  • go.sum — dependency checksums
  • cmd/server/main.go — entry point
  • internal/store/store.go — DB connection, schema, migrations
  • internal/store/projects.go — project queries
  • internal/store/stages.go — stage queries
  • internal/store/registries.go — registry queries
  • internal/store/settings.go — settings queries
  • internal/store/instances.go — instance queries
  • internal/store/deploys.go — deploy history queries

Acceptance Criteria

  • go mod tidy succeeds
  • 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/sqlite for CGo-free SQLite
  • Use go-chi/chi/v5 for 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-watcher with 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 IGNORE seed
  • Models extracted to internal/store/models.go for clean separation

Key files

  • go.mod — module definition with modernc.org/sqlite, chi, yaml, uuid, cron
  • cmd/server/main.go — entry point that creates data dir, opens store, defers close
  • internal/store/store.go — DB connection, pragmas, schema DDL, migration
  • internal/store/models.go — all entity structs (Project, Stage, Registry, Settings, Instance, Deploy, DeployLog)
  • internal/store/projects.go — full CRUD
  • internal/store/stages.go — full CRUD with bool-to-int conversion for SQLite
  • internal/store/registries.go — full CRUD
  • internal/store/settings.go — Get/Update (single-row upsert)
  • internal/store/instances.go — full CRUD + UpdateStatus
  • internal/store/deploys.go — Create, GetByID, GetByProjectID, GetRecent, UpdateDeployStatus, SetDeployInstanceID, AppendDeployLog, GetDeployLogs

Conventions established

  • UUIDs generated via github.com/google/uuid on 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.Errorf and %w for 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 boolToInt helper
  • JSON-encoded maps stored as TEXT for env and volumes fields

What Phase 2 needs to know

  • store.New(dbPath) returns a *Store that is ready to use — no additional init needed
  • The settings table is pre-seeded with a row (id=1) so GetSettings always works
  • Registry token and settings npm_password are stored as plain text — Phase 2 (Crypto) should add encryption/decryption around these fields
  • go.sum does not exist yet — run go mod tidy after Go is available to generate it