Skip to content

Commit

Permalink
feat: add Migrator commands
Browse files Browse the repository at this point in the history
- migrate
- rollback
- create
- unlock
  • Loading branch information
bevzzz committed Nov 26, 2024
1 parent af1e62f commit e9fd1e5
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 26 deletions.
1 change: 1 addition & 0 deletions cmd/bundb/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ func main() {
log.SetPrefix("bundb: ")
// TODO: use buncli.New(buncli.FromPlugin()) to read config from plugin
if err := buncli.Run(os.Args, nil); err != nil {
log.Fatal(err)
}
}
21 changes: 6 additions & 15 deletions extra/buncli/auto.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/urfave/cli/v2"
)

// CmdAuto creates the auto command hierarchy.
func CmdAuto(c *Config) *cli.Command {
return &cli.Command{
Name: "auto",
Expand All @@ -16,36 +17,26 @@ func CmdAuto(c *Config) *cli.Command {
flagTx,
},
Action: func(ctx *cli.Context) error {
return autoCreate(ctx, c)
return runAutoCreate(ctx, c)
},
},
&cli.Command{
Name: "migrate",
Usage: "Generate SQL migrations and apply them right away",
Action: func(ctx *cli.Context) error {
return autoMigrate(ctx, c)
return runAutoMigrate(ctx, c)
},
},
},
}
}

var (
// flagTx adds --transactional flag.
flagTx = &cli.BoolFlag{
Name: "tx",
Aliases: []string{"transactional"},
Usage: "write migrations to .tx.(up|down).sql file, they will be marked as transactional",
Value: false,
}
)

func autoMigrate(ctx *cli.Context, c *Config) error {
_, err := c.AutoMigrator.Migrate(ctx.Context)
func runAutoMigrate(ctx *cli.Context, c *Config) error {
_, err := c.AutoMigrator.Migrate(ctx.Context, c.MigrateOptions...)
return err
}

func autoCreate(ctx *cli.Context, c *Config) error {
func runAutoCreate(ctx *cli.Context, c *Config) error {
var err error
if flagTx.Get(ctx) {
_, err = c.AutoMigrator.CreateTxSQLMigrations(ctx.Context)
Expand Down
25 changes: 14 additions & 11 deletions extra/buncli/buncli.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
/*
TODO:
- Commands:
- init - Create migration+locks tables [--cmd to add cmd/ folder structure]
- migrate - Apply database migrations
- rollback - Rollback the last migration group
- create - Create template SQL migration filex [--go | --sql | --transactional]
- unlock - Unlock locks table
- provide NewCommand() *cli.Command intead of the cli.App, so that buncli could be embeded in the existing CLIs
- configure logging and verbosity
- (experimental, low prio) add FromPlugin() to read config from plugin and use from cmd/bundb.
- Commands:
- init - Create migration+locks tables [--no-cmd to omit cmd/ folder]
- provide NewCommand() *cli.Command intead of the cli.App, so that buncli could be embeded in the existing CLIs
- configure logging and verbosity
- (experimental, low prio) add FromPlugin() to read config from plugin and use from cmd/bundb.
*/
package buncli

Expand All @@ -29,16 +25,23 @@ var bunApp = &cli.App{
// New creates a new CLI application for managing bun migrations.
func New(c *Config) *App {
bunApp.Commands = cli.Commands{
CmdMigrate(c),
CmdRollback(c),
CmdCreate(c),
CmdAuto(c),
CmdUnlock(c),
}
return &App{
App: bunApp,
}
}

type Config struct {
DB *bun.DB
AutoMigrator *migrate.AutoMigrator
DB *bun.DB
AutoMigrator *migrate.AutoMigrator
Migrations *migrate.Migrations
MigrateOptions []migrate.MigrationOption
GoMigrationOptions []migrate.GoMigrationOption
}

// Run calls cli.App.Run and returns its error.
Expand Down
122 changes: 122 additions & 0 deletions extra/buncli/migrator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package buncli

import (
"github.com/uptrace/bun/migrate"
"github.com/urfave/cli/v2"
)

// CmdMigrate creates a migrate command.
func CmdMigrate(c *Config) *cli.Command {
return &cli.Command{
Name: "migrate",
Usage: "Apply database migrations",
Action: func(ctx *cli.Context) error {
return runMigrate(ctx, c)
},
}
}

func runMigrate(ctx *cli.Context, c *Config) error {
m := migrate.NewMigrator(c.DB, c.Migrations)
_, err := m.Migrate(ctx.Context, c.MigrateOptions...)
return err
}

// CmdRollback creates a rollback command.
func CmdRollback(c *Config) *cli.Command {
return &cli.Command{
Name: "rollback",
Usage: "Rollback the last migration group",
Action: func(ctx *cli.Context) error {
return runRollback(ctx, c)
},
}
}

func runRollback(ctx *cli.Context, c *Config) error {
m := migrate.NewMigrator(c.DB, c.Migrations)
_, err := m.Rollback(ctx.Context, c.MigrateOptions...)
return err
}

func CmdCreate(c *Config) *cli.Command {
return &cli.Command{
Name: "create",
Usage: "Create a new migration file template",
Args: true, // TODO: add usage example and description
Flags: []cli.Flag{
flagTx,
flagGo,
flagSQL,
},
Action: func(ctx *cli.Context) error {
return runCreate(ctx, c)
},
}
}

var (
// createGo controls the type of the template (Go/SQL) the Migrator should create.
createGo bool

// flagTx adds --transactional flag.
flagTx = &cli.BoolFlag{
Name: "tx",
Aliases: []string{"transactional"},
Usage: "write migrations to .tx.(up|down).sql file, they will be marked as transactional",
Value: false,
}

// flagGo adds --go flag. Prefer checking 'createGo' as the flagGo and flagSQL are mutually exclusive and it is how they synchronize.
flagGo = &cli.BoolFlag{
Name: "go",
Usage: "create .go migration file",
Value: false,
Destination: &createGo,
}

// flagSQL adds --sql flag. Prefer checking 'createGo' as the flagGo and flagSQL are mutually exclusive and it is how they synchronize.
flagSQL = &cli.BoolFlag{
Name: "sql",
Usage: "create .sql migrations",
Value: true,
Action: func(ctx *cli.Context, b bool) error {
createGo = !b
return nil
},
}
)

func runCreate(ctx *cli.Context, c *Config) error {
var err error
m := migrate.NewMigrator(c.DB, c.Migrations)
name := ctx.Args().First()

if createGo {
_, err = m.CreateGoMigration(ctx.Context, name, c.GoMigrationOptions...)
return err
}

if flagTx.Get(ctx) {
_, err = m.CreateTxSQLMigrations(ctx.Context, name)
} else {
_, err = m.CreateSQLMigrations(ctx.Context, name)
}
return err
}

// CmdUnlock creates an unlock command.
func CmdUnlock(c *Config) *cli.Command {
return &cli.Command{
Name: "unlock",
Usage: "Unlock migration locks table",
Action: func(ctx *cli.Context) error {
return runUnlock(ctx, c)
},
}
}

func runUnlock(ctx *cli.Context, c *Config) error {
m := migrate.NewMigrator(c.DB, c.Migrations)
return m.Unlock(ctx.Context)
}

0 comments on commit e9fd1e5

Please sign in to comment.