42307f285f
encapi's schema was a cumulative IF NOT EXISTS blob re-executed inline on every start: it grows forever, records nothing, and cannot express a change that is not a fresh CREATE. golib owns that mechanism now, so encapi keeps the SQL and drops the runner. - Move the DDL verbatim into migrations/0001_init.sql, embedded via migrations.FS. It stays IF NOT EXISTS-guarded, so the first start against the live database re-runs it as a no-op and only lands the schema_migrations row. - Build the pool with pg.NewMigrated under the advisory lock named encapi-migrations, and delete the inline migrate(). database.New now takes a context and a logger; main.go hands it the signal context so a start blocked on the migration lock still dies on SIGTERM. - Render the DSN with pg.DSN. The env var contract is untouched — the fields are still resolved by internal/config, because encapi defaults DBUSER and DBNAME to "encapi" where pg.DSNFromEnv treats both as required. - Guard the set: embedded files must match migrations/, every CREATE must be idempotent, the derived lock key is pinned, and a container test proves the adoption path over a database that predates schema_migrations. - Plumb GOPRIVATE=git.unkin.net for the first cross-repo Go dependency: exported by the Makefile, set in the Dockerfile and the woodpecker Go steps, documented in the README.
17 lines
574 B
Go
17 lines
574 B
Go
// Package migrations embeds encapi's SQL schema so the server carries it in
|
|
// the binary and applies it at startup, with no separately deployed copy to
|
|
// drift out of sync.
|
|
package migrations
|
|
|
|
import "embed"
|
|
|
|
// FS holds every numbered migration; lexical filename order is version order.
|
|
//
|
|
//go:embed *.sql
|
|
var FS embed.FS
|
|
|
|
// LockName names the cluster-wide advisory lock replicas contend for while
|
|
// migrating. golib derives the key as FNV-1a/64 of this name, so every replica
|
|
// migrating this database must agree on the string.
|
|
const LockName = "encapi-migrations"
|