From c2f5dbeeca5e30eec55439964cb574859eda9095 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sun, 19 Apr 2026 19:25:52 -0600 Subject: [PATCH] doc(skills): pgmigrate clarificaton --- skills/use-sql-migrate-postgres/SKILL.md | 47 +++++++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/skills/use-sql-migrate-postgres/SKILL.md b/skills/use-sql-migrate-postgres/SKILL.md index 5413e44..1344fb4 100644 --- a/skills/use-sql-migrate-postgres/SKILL.md +++ b/skills/use-sql-migrate-postgres/SKILL.md @@ -19,19 +19,54 @@ PG_URL='postgres://user:pass@localhost:5432/mydb?sslmode=disable' ## Go library +Use `sqlmigrate.Collect(fsys, subpath)` first to parse the embedded files. + +**`//go:embed` constraint:** embed cannot traverse `..`, so the embed directive must live in a package that is at or above the `sql/migrations/` directory. Pass `fs.FS` down to migration helpers rather than embedding inside them. + ```go import ( + "embed" + "io/fs" + "github.com/jackc/pgx/v5" "github.com/therootcompany/golib/database/sqlmigrate" "github.com/therootcompany/golib/database/sqlmigrate/pgmigrate" ) -// MUST: use pgx.Connect (single conn), not pgxpool.New -conn, err := pgx.Connect(ctx, pgURL) -defer func() { _ = conn.Close(ctx) }() +//go:embed sql/migrations +var migrationsFS embed.FS -runner := pgmigrate.New(conn) -applied, err := sqlmigrate.Latest(ctx, runner, scripts) +func runMigrations(ctx context.Context, pgURL string) error { + scripts, err := sqlmigrate.Collect(migrationsFS, "sql/migrations") + if err != nil { + return err + } + + // MUST: use pgx.Connect (single conn), not pgxpool.New + conn, err := pgx.Connect(ctx, pgURL) + if err != nil { + return err + } + defer func() { _ = conn.Close(ctx) }() + + runner := pgmigrate.New(conn) + _, err = sqlmigrate.Latest(ctx, runner, scripts) + return err +} +``` + +### Key types + +```go +// sqlmigrate.Script — one migration pair (up + down SQL + name + ID) +// sqlmigrate.Migration — name + ID only (returned by Applied, Latest, etc.) +// sqlmigrate.Status — Applied []Migration + Pending []Migration + +scripts, err := sqlmigrate.Collect(fsys, subpath) // parse fs.FS → []Script +applied, err := sqlmigrate.Latest(ctx, r, scripts) // apply all pending → []Migration +applied, err := sqlmigrate.Up(ctx, r, scripts, n) // apply n migrations +rolled, err := sqlmigrate.Down(ctx, r, scripts, n) // roll back n migrations +status, err := sqlmigrate.GetStatus(ctx, r, scripts) ``` ## Schema multi-tenancy @@ -61,4 +96,4 @@ runner := pgmigrate.New(conn) - `ON CONFLICT DO NOTHING` for idempotent seeds - String concatenation: `id || CHR(9) || name` (used by sync query) - Timestamps: `TIMESTAMP DEFAULT CURRENT_TIMESTAMP` -- Error code 42P01 = table doesn't exist (handled automatically by pgmigrate) +- Error code 42P01 = table doesn't exist (handled automatically by pgmigrate for initial migration)