Rewrites CI to use a multi-stage Dockerfile per REPO_POLICIES:
- Lint stage: golangci/golangci-lint:v2.1.6-alpine runs make fmt-check
and make lint
- Build stage: golang:1.24.4-alpine runs make test, then builds binary
with CGO enabled (required for mattn/go-sqlite3)
- Runtime stage: alpine:3.21 copies binary, runs as non-root user
All base images pinned by @sha256 hash.
CI workflow simplified to just 'docker build .' since the Dockerfile
already runs make check (fmt-check + lint + test).
Makefile aligned with REPO_POLICIES:
- check target uses prereqs (fmt-check lint test)
- fmt-check is read-only (gofmt -l, not go fmt)
- Added docker and hooks targets
- test uses -race -timeout 30s
Added .dockerignore for efficient build context.
Two issues caused CI failures:
1. golangci-lint v2.10.1 requires Go >= 1.25.0, but the project uses
Go 1.24.4 (from go.mod). The previous `go install` approach tried
to compile golangci-lint from source, which fails due to the Go
version mismatch. Fix: download the pre-built binary via the
official install script, pinned to the same commit SHA (5d1e709)
for security.
2. TestBackupAndRestore fails because vacuumDatabase() shells out to
the `sqlite3` CLI binary, which is not installed in the CI runner
image. Fix: install sqlite3 via apt-get in CI.