package migratecli import ( "context" "fmt" "gitea.auvem.com/go-toolkit/dbx" "gitea.auvem.com/go-toolkit/migrate" "github.com/pressly/goose/v3" "github.com/urfave/cli/v3" ) // MigrateCmd returns the main migrate command. func MigrateCmd() *cli.Command { return &cli.Command{ Name: "migrate", Usage: "Migrate the database", Commands: AllSubcommands(), } } // AllSubcommands returns all subcommands of the migrate command. func AllSubcommands() []*cli.Command { return []*cli.Command{ MigrateStatusCmd(), MigrateCreateCmd(), MigrateUpCmd(), MigrateUpToCmd(), MigrateDownCmd(), MigrateDownToCmd(), MigrateRedoCmd(), } } // MigrateStatusCmd returns a command to get database migration status. func MigrateStatusCmd() *cli.Command { return &cli.Command{ Name: "status", Usage: "Get database migration status", Action: func(ctx context.Context, cmd *cli.Command) error { if err := goose.Status(dbx.SQLO(), migrate.MigrationsConfig().BasePath); err != nil { return fmt.Errorf("couldn't get migration status: %v", err) } return nil }, } } // MigrateCreateCmd returns a command to create a new migration. func MigrateCreateCmd() *cli.Command { return &cli.Command{ Name: "create", Usage: "Create a new migration", Arguments: []cli.Argument{ &cli.StringArg{Name: "name", UsageText: "Name of the migration"}, &cli.StringArg{Name: "type", UsageText: "Type of the migration (e.g., sql, go)"}, }, Flags: []cli.Flag{ &cli.BoolFlag{ Name: "sequential", Usage: "Create migration in sequential mode", }, }, Action: func(ctx context.Context, cmd *cli.Command) error { sequential := cmd.Bool("sequential") if sequential { goose.SetSequential(sequential) } if err := goose.Create(dbx.SQLO(), "migrations", cmd.StringArg("name"), cmd.StringArg("type")); err != nil { return fmt.Errorf("couldn't create migration: %v", err) } return nil }, } } // MigrateUpCmd returns a command to apply all available database migrations. func MigrateUpCmd() *cli.Command { return &cli.Command{ Name: "up", Usage: "Apply all available database migrations", Action: func(ctx context.Context, cmd *cli.Command) error { if err := goose.Up(dbx.SQLO(), migrate.MigrationsConfig().BasePath); err != nil { return fmt.Errorf("couldn't apply migrations: %v", err) } return nil }, } } // MigrateUpToCmd returns a command to apply all available database migrations up to a specific version. func MigrateUpToCmd() *cli.Command { return &cli.Command{ Name: "up-to", Usage: "Apply all available database migrations up to a specific version", Arguments: []cli.Argument{ &cli.Int64Arg{ Name: "version", UsageText: "Target version to migrate up to", }, }, Action: func(ctx context.Context, cmd *cli.Command) error { version := cmd.Int64("version") if err := goose.UpTo(dbx.SQLO(), migrate.MigrationsConfig().BasePath, version); err != nil { return fmt.Errorf("couldn't apply migrations to target version %d: %v", version, err) } return nil }, } } // MigrateDownCmd returns a command to rollback the most recent database migration. func MigrateDownCmd() *cli.Command { return &cli.Command{ Name: "down", Usage: "Rollback the most recent database migration", Action: func(ctx context.Context, cmd *cli.Command) error { if err := goose.Down(dbx.SQLO(), migrate.MigrationsConfig().BasePath); err != nil { return fmt.Errorf("couldn't rollback migration: %v", err) } return nil }, } } // MigrateDownToCmd returns a command to rollback all database migrations down to a specific version. func MigrateDownToCmd() *cli.Command { return &cli.Command{ Name: "down-to", Usage: "Rollback all database migrations down to a specific version", Arguments: []cli.Argument{ &cli.Int64Arg{ Name: "version", UsageText: "Target version to rollback to", }, }, Action: func(ctx context.Context, cmd *cli.Command) error { version := cmd.Int64("version") if err := goose.DownTo(dbx.SQLO(), migrate.MigrationsConfig().BasePath, version); err != nil { return fmt.Errorf("couldn't rollback migrations to target version %d: %v", version, err) } return nil }, } } // MigrateRedoCmd returns a command to rollback the most recent database migration and reapply it. func MigrateRedoCmd() *cli.Command { return &cli.Command{ Name: "redo", Usage: "Rollback the most recent database migration and reapply it", Action: func(ctx context.Context, cmd *cli.Command) error { if err := goose.Redo(dbx.SQLO(), migrate.MigrationsConfig().BasePath); err != nil { return fmt.Errorf("couldn't redo migration: %v", err) } return nil }, } }