xtablo-source/backend/internal/db/migrate.go
Arthur Belleville 77e37cb21b
feat(07-01): embed.go + RunMigrations + HealthzHandler()/ReadyzHandler() split
- backend/embed.go: package assets with //go:embed all:static and //go:embed migrations
- backend/internal/db/migrate.go: RunMigrations using pgx/v5/stdlib bridge to goose.Up()
- backend/internal/web/handlers.go: HealthzHandler() no-arg liveness + ReadyzHandler(pinger) readiness
- backend/internal/web/handlers_test.go: TestHealthz_OK (no pinger), TestReadyz_OK, TestReadyz_Down added; TestHealthz_Down deleted
2026-05-15 18:14:26 +02:00

44 lines
1.3 KiB
Go

package db
import (
"context"
"database/sql"
"embed"
"fmt"
"github.com/jackc/pgx/v5/pgxpool"
_ "github.com/jackc/pgx/v5/stdlib" // pgx/v5 driver for database/sql
"github.com/pressly/goose/v3"
)
// RunMigrations applies all pending goose migrations from the embedded FS.
// It uses the pgx/v5/stdlib bridge so that goose's database/sql interface
// can speak to the same Postgres as the rest of the application.
//
// Call RunMigrations once at startup, before constructing the router.
// goose.Up is idempotent — already-applied migrations are skipped.
func RunMigrations(ctx context.Context, pool *pgxpool.Pool, migrationsFS embed.FS) error {
// Extract the DSN from the pool's connection config.
connConfig := pool.Config().ConnConfig
dsn := connConfig.ConnString()
// Open a database/sql connection for goose. The pgx/v5 stdlib driver is
// registered by the blank import above.
sqlDB, err := sql.Open("pgx/v5", dsn)
if err != nil {
return fmt.Errorf("migrate: open sql.DB: %w", err)
}
defer sqlDB.Close()
// Point goose at the embedded FS so no on-disk files are needed.
goose.SetBaseFS(migrationsFS)
if err := goose.SetDialect("postgres"); err != nil {
return fmt.Errorf("migrate: set dialect: %w", err)
}
if err := goose.Up(sqlDB, "migrations"); err != nil {
return fmt.Errorf("migrate: goose up: %w", err)
}
return nil
}