// Command migrate manages database migrations. // // Usage: // // go run ./cmd/migrate up apply all pending migrations // go run ./cmd/migrate down roll back the most recent group // go run ./cmd/migrate status list migrations and whether they ran // go run ./cmd/migrate new NAME create a Go migration scaffold named // _NAME.go in // internal/database/migrations/ package main import ( "context" "fmt" "os" _ "github.com/joho/godotenv/autoload" "git.k6n.net/mats/fullstack-template/internal/config" "git.k6n.net/mats/fullstack-template/internal/database" ) func main() { cmd := "up" if len(os.Args) > 1 { cmd = os.Args[1] } if cmd != "up" && cmd != "down" && cmd != "status" && cmd != "new" { fmt.Fprintln(os.Stderr, "usage: migrate [up|down|status|new NAME]") os.Exit(2) } cfg, err := config.Load() if err != nil { fatal(err) } db, err := database.Open(cfg) if err != nil { fatal(err) } defer db.Close() ctx := context.Background() m := database.NewMigrator(db) switch cmd { case "up": if err := m.Init(ctx); err != nil { fatal(err) } group, err := m.Migrate(ctx) if err != nil { fatal(err) } if group.IsZero() { fmt.Println("no pending migrations") } else { fmt.Printf("applied %d migration(s) (group %d)\n", len(group.Migrations), group.ID) } case "down": if err := m.Init(ctx); err != nil { fatal(err) } group, err := m.Rollback(ctx) if err != nil { fatal(err) } if group.IsZero() { fmt.Println("nothing to roll back") } else { fmt.Printf("rolled back %d migration(s) (group %d)\n", len(group.Migrations), group.ID) } case "status": if err := m.Init(ctx); err != nil { fatal(err) } migrations, err := m.MigrationsWithStatus(ctx) if err != nil { fatal(err) } for _, mig := range migrations { state := "pending" if mig.IsApplied() { state = "applied" } fmt.Printf("%-8s %s %s\n", state, mig.Name, mig.Comment) } case "new": if len(os.Args) < 3 { fmt.Fprintln(os.Stderr, "usage: migrate new NAME (snake_case)") os.Exit(2) } file, err := m.CreateGoMigration(ctx, os.Args[2]) if err != nil { fatal(err) } fmt.Println("created", file.Path) } } func fatal(err error) { fmt.Fprintln(os.Stderr, "migrate:", err) os.Exit(1) }