sessions/cmd/sessions/internal/db/db.go

174 lines
3.7 KiB
Go

package db
import (
"fmt"
"strconv"
"strings"
"gitea.dwysokinski.me/twhelp/sessions/cmd/sessions/internal"
"gitea.dwysokinski.me/twhelp/sessions/internal/bundb/migrations"
"github.com/urfave/cli/v2"
"go.uber.org/zap"
)
func New() *cli.Command {
return &cli.Command{
Name: "db",
Usage: "Manages database migrations",
Subcommands: []*cli.Command{
newMigrateCmd(),
newRollbackCmd(),
newCreateCmd(),
newStatusCmd(),
},
}
}
func newMigrateCmd() *cli.Command {
return &cli.Command{
Name: "migrate",
Usage: "Migrates database",
Action: func(c *cli.Context) error {
logger := zap.L()
db, err := internal.NewBunDB()
if err != nil {
return fmt.Errorf("internal.NewBunDB: %w", err)
}
defer func() {
_ = db.Close()
}()
migrator := migrations.NewMigrator(db)
if err = migrator.Init(c.Context); err != nil {
return fmt.Errorf("migrator.Init: %w", err)
}
group, err := migrator.Migrate(c.Context)
if err != nil {
return fmt.Errorf("migrator.Migrate: %w", err)
}
if group.ID == 0 {
logger.Info("there are no new migrations to run")
return nil
}
logger.Info("migrated to "+strconv.FormatInt(group.ID, 10), zap.Int64("id", group.ID))
return nil
},
}
}
func newRollbackCmd() *cli.Command {
return &cli.Command{
Name: "rollback",
Usage: "Rollbacks the last migration group",
Action: func(c *cli.Context) error {
logger := zap.L()
db, err := internal.NewBunDB()
if err != nil {
return fmt.Errorf("internal.NewBunDB: %w", err)
}
defer func() {
_ = db.Close()
}()
migrator := migrations.NewMigrator(db)
group, err := migrator.Rollback(c.Context)
if err != nil {
return fmt.Errorf("migrator.Rollback: %w", err)
}
if group.ID == 0 {
logger.Info("there are no groups to roll back")
return nil
}
logger.Info("rolled back "+strconv.FormatInt(group.ID, 10), zap.Int64("id", group.ID))
return nil
},
}
}
func newCreateCmd() *cli.Command {
return &cli.Command{
Name: "create",
Usage: "Creates migration",
Subcommands: []*cli.Command{
{
Name: "go",
Usage: "Creates Go migration",
Action: func(c *cli.Context) error {
logger := zap.L()
migrator := migrations.NewMigrator(nil)
mf, err := migrator.CreateGoMigration(c.Context, strings.Join(c.Args().Slice(), "_"))
if err != nil {
return fmt.Errorf("migrator.CreateGoMigration: %w", err)
}
logger.Info("created migration", zap.String("name", mf.Name), zap.String("path", mf.Path))
return nil
},
},
{
Name: "sql",
Usage: "Creates SQL migration",
Action: func(c *cli.Context) error {
logger := zap.L()
migrator := migrations.NewMigrator(nil)
files, err := migrator.CreateSQLMigrations(c.Context, strings.Join(c.Args().Slice(), "_"))
if err != nil {
return fmt.Errorf("migrator.CreateSQLMigrations: %w", err)
}
for _, mf := range files {
logger.Info("created migration", zap.String("name", mf.Name), zap.String("path", mf.Path))
}
return nil
},
},
},
}
}
func newStatusCmd() *cli.Command {
return &cli.Command{
Name: "status",
Usage: "Prints migrations status",
Action: func(c *cli.Context) error {
logger := zap.L()
db, err := internal.NewBunDB()
if err != nil {
return fmt.Errorf("internal.NewBunDB: %w", err)
}
defer func() {
_ = db.Close()
}()
migrator := migrations.NewMigrator(db)
ms, err := migrator.MigrationsWithStatus(c.Context)
if err != nil {
return fmt.Errorf("migrator.MigrationsWithStatus: %w", err)
}
logger.Info("migrations: " + ms.String())
logger.Info("last migration group: " + ms.LastGroup().String())
logger.Info("unapplied: " + ms.Unapplied().String())
return nil
},
}
}