Run applies all pending migrations using embedded SQL files. Logs to the provided logger and always prints migration status to stdout. Returns an error if migrations fail. ErrNoChange is treated as success (already up to date).
(databaseURL string, log *slog.Logger)
| 22 | // Returns an error if migrations fail. |
| 23 | // ErrNoChange is treated as success (already up to date). |
| 24 | func Run(databaseURL string, log *slog.Logger) error { |
| 25 | if databaseURL == "" { |
| 26 | return fmt.Errorf("DATABASE_URL is required for migrations") |
| 27 | } |
| 28 | |
| 29 | databaseURL = ensureSSLMode(databaseURL) |
| 30 | |
| 31 | _, _ = fmt.Fprintln(os.Stdout, "[migrate] running migrations from embedded binary") |
| 32 | log.Info("running migrations", "path", "embedded") |
| 33 | |
| 34 | source, err := iofs.New(migrationsFS, "migrations") |
| 35 | if err != nil { |
| 36 | return fmt.Errorf("create embedded migrate source: %w", err) |
| 37 | } |
| 38 | |
| 39 | m, err := migrate.NewWithSourceInstance("iofs", source, databaseURL) |
| 40 | if err != nil { |
| 41 | return fmt.Errorf("create migrate instance: %w", err) |
| 42 | } |
| 43 | defer func() { _, _ = m.Close() }() |
| 44 | |
| 45 | if err := m.Up(); err != nil && err != migrate.ErrNoChange { |
| 46 | fmt.Fprintf(os.Stderr, "[migrate] failed: %v\n", err) |
| 47 | return fmt.Errorf("migration up: %w", err) |
| 48 | } |
| 49 | |
| 50 | if err == migrate.ErrNoChange { |
| 51 | _, _ = fmt.Fprintln(os.Stdout, "[migrate] already up to date") |
| 52 | log.Info("migrations: already up to date") |
| 53 | return nil |
| 54 | } |
| 55 | |
| 56 | version, _, _ := m.Version() |
| 57 | msg := fmt.Sprintf("[migrate] applied successfully (version %d)", version) |
| 58 | _, _ = fmt.Fprintln(os.Stdout, msg) |
| 59 | log.Info("migrations applied successfully", "version", version) |
| 60 | return nil |
| 61 | } |
| 62 | |
| 63 | // Open returns a migrate instance using embedded migrations, for use by the CLI (up/down/force/version). |
| 64 | // Caller must call m.Close() when done. |
nothing calls this directly
no test coverage detected