package main import ( "flag" "fmt" "os" "mengstack/internal/config" "mengstack/migrations" "github.com/golang-migrate/migrate/v4" _ "github.com/golang-migrate/migrate/v4/database/postgres" "github.com/golang-migrate/migrate/v4/source/iofs" ) func main() { if len(os.Args) < 2 { fmt.Println("Usage: migrate [flags]") fmt.Println("Commands: up, down, status") fmt.Println(" up [steps] Run pending migrations (optional step count)") fmt.Println(" down [steps] Rollback migrations (optional step count, 0=all)") fmt.Println(" status Show current migration status") os.Exit(1) } cfg, err := config.Load() if err != nil { fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err) os.Exit(1) } dsn := fmt.Sprintf( "postgres://%s:%s@%s:%d/%s?sslmode=%s&search_path=public", cfg.Database.User, cfg.Database.Password, cfg.Database.Host, cfg.Database.Port, cfg.Database.DBName, cfg.Database.SSLMode, ) source, err := iofs.New(migrations.Files, ".") if err != nil { fmt.Fprintf(os.Stderr, "Error creating migration source: %v\n", err) os.Exit(1) } m, err := migrate.NewWithSourceInstance("iofs", source, dsn) if err != nil { fmt.Fprintf(os.Stderr, "Error creating migrator: %v\n", err) os.Exit(1) } cmd := os.Args[1] switch cmd { case "up": steps := 0 fs := flag.NewFlagSet("up", flag.ExitOnError) fs.IntVar(&steps, "steps", 0, "number of migrations to run (0=all)") fs.Parse(os.Args[2:]) if steps > 0 { err = m.Steps(steps) } else { err = m.Up() } if err != nil && err != migrate.ErrNoChange { fmt.Fprintf(os.Stderr, "Migration error: %v\n", err) os.Exit(1) } if err == migrate.ErrNoChange { fmt.Println("No pending migrations") } else { fmt.Println("Migrations applied successfully") } case "down": steps := 1 fs := flag.NewFlagSet("down", flag.ExitOnError) fs.IntVar(&steps, "steps", 1, "number of migrations to rollback (0=all)") fs.Parse(os.Args[2:]) if steps == 0 { err = m.Down() } else { err = m.Steps(-steps) } if err != nil && err != migrate.ErrNoChange { fmt.Fprintf(os.Stderr, "Rollback error: %v\n", err) os.Exit(1) } fmt.Println("Rollback completed") case "status": v, dirty, err := m.Version() if err != nil && err != migrate.ErrNoChange { fmt.Fprintf(os.Stderr, "Status error: %v\n", err) os.Exit(1) } if err == migrate.ErrNoChange { fmt.Println("No migrations applied yet") } else { fmt.Printf("Current version: %d, dirty: %v\n", v, dirty) } default: fmt.Fprintf(os.Stderr, "Unknown command: %s\n", cmd) os.Exit(1) } }