feat: parse version prefix from migration filenames #33
@@ -119,7 +119,7 @@ func (s *Database) connect(ctx context.Context) error {
|
|||||||
s.db = db
|
s.db = db
|
||||||
s.log.Info("database connected")
|
s.log.Info("database connected")
|
||||||
|
|
||||||
return s.runMigrations(ctx)
|
return ApplyMigrations(ctx, s.db, s.log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectMigrations reads the embedded schema directory and returns
|
// collectMigrations reads the embedded schema directory and returns
|
||||||
@@ -159,9 +159,11 @@ func ensureMigrationsTable(ctx context.Context, db *sql.DB) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyMigrations applies all pending migrations to db, using log for
|
// ApplyMigrations applies all pending migrations to db. An optional logger
|
||||||
// informational output (may be nil for silent operation).
|
// may be provided for informational output; pass nil for silent operation.
|
||||||
func applyMigrations(ctx context.Context, db *sql.DB, log *slog.Logger) error {
|
// This is exported so tests can apply the real schema without the full fx
|
||||||
|
// lifecycle.
|
||||||
|
func ApplyMigrations(ctx context.Context, db *sql.DB, log *slog.Logger) error {
|
||||||
if err := ensureMigrationsTable(ctx, db); err != nil {
|
if err := ensureMigrationsTable(ctx, db); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -228,18 +230,7 @@ func applyMigrations(ctx context.Context, db *sql.DB, log *slog.Logger) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Database) runMigrations(ctx context.Context) error {
|
|
||||||
return applyMigrations(ctx, s.db, s.log)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DB returns the underlying sql.DB.
|
// DB returns the underlying sql.DB.
|
||||||
func (s *Database) DB() *sql.DB {
|
func (s *Database) DB() *sql.DB {
|
||||||
return s.db
|
return s.db
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyMigrations applies all migrations to the given database.
|
|
||||||
// This is useful for testing where you want to use the real schema
|
|
||||||
// without the full fx lifecycle.
|
|
||||||
func ApplyMigrations(db *sql.DB) error {
|
|
||||||
return applyMigrations(context.Background(), db, nil)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ func TestApplyMigrations(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// Apply migrations should succeed.
|
// Apply migrations should succeed.
|
||||||
if err := ApplyMigrations(db); err != nil {
|
if err := ApplyMigrations(context.Background(), db, nil); err != nil {
|
||||||
t.Fatalf("ApplyMigrations failed: %v", err)
|
t.Fatalf("ApplyMigrations failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,11 +131,11 @@ func TestApplyMigrationsIdempotent(t *testing.T) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// Apply twice should succeed (idempotent).
|
// Apply twice should succeed (idempotent).
|
||||||
if err := ApplyMigrations(db); err != nil {
|
if err := ApplyMigrations(context.Background(), db, nil); err != nil {
|
||||||
t.Fatalf("first ApplyMigrations failed: %v", err)
|
t.Fatalf("first ApplyMigrations failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ApplyMigrations(db); err != nil {
|
if err := ApplyMigrations(context.Background(), db, nil); err != nil {
|
||||||
t.Fatalf("second ApplyMigrations failed: %v", err)
|
t.Fatalf("second ApplyMigrations failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func setupTestDB(t *testing.T) *sql.DB {
|
|||||||
t.Fatalf("failed to open test db: %v", err)
|
t.Fatalf("failed to open test db: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := database.ApplyMigrations(db); err != nil {
|
if err := database.ApplyMigrations(context.Background(), db, nil); err != nil {
|
||||||
t.Fatalf("failed to apply migrations: %v", err)
|
t.Fatalf("failed to apply migrations: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func setupStatsTestDB(t *testing.T) *sql.DB {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := database.ApplyMigrations(db); err != nil {
|
if err := database.ApplyMigrations(context.Background(), db, nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
t.Cleanup(func() { db.Close() })
|
t.Cleanup(func() { db.Close() })
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package imgcache
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
@@ -193,7 +194,7 @@ func setupServiceTestDB(t *testing.T) *sql.DB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use the real production schema via migrations
|
// Use the real production schema via migrations
|
||||||
if err := database.ApplyMigrations(db); err != nil {
|
if err := database.ApplyMigrations(context.Background(), db, nil); err != nil {
|
||||||
t.Fatalf("failed to apply migrations: %v", err)
|
t.Fatalf("failed to apply migrations: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user