-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactoring commands and configs as well update linters
- Loading branch information
Showing
18 changed files
with
349 additions
and
296 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,112 +1,136 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"log/slog" | ||
"sort" | ||
|
||
"github.com/weesvc/weesvc-gorilla/internal/config" | ||
|
||
"github.com/spf13/viper" | ||
|
||
"github.com/jinzhu/gorm" | ||
"github.com/pkg/errors" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/weesvc/weesvc-gorilla/internal/app" | ||
"github.com/weesvc/weesvc-gorilla/internal/migrations" | ||
) | ||
|
||
var migrateCmd = &cobra.Command{ | ||
Use: "migrate", | ||
Short: "Readies the application database", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
number, _ := cmd.Flags().GetInt("number") | ||
dryRun, _ := cmd.Flags().GetBool("dry-run") | ||
func newMigrateCommand(config *config.Config) *cobra.Command { | ||
migrateCmd := &cobra.Command{ | ||
Use: "migrate", | ||
Short: "Readies the application database", | ||
RunE: func(cmd *cobra.Command, _ []string) error { | ||
svc, err := app.New(config) | ||
if err != nil { | ||
return err | ||
} | ||
defer func() { | ||
_ = svc.Close() | ||
}() | ||
return migrate(cmd, svc) | ||
}, | ||
} | ||
|
||
if dryRun { | ||
logrus.Info("=== DRY RUN ===") | ||
} | ||
migrateCmd.Flags().Int("number", -1, "the migration to run forwards until; if not set, will run all migrations") | ||
migrateCmd.Flags().Bool("dry-run", false, "print out migrations to be applied without running them") | ||
|
||
sort.Slice(migrations.Migrations, func(i, j int) bool { | ||
return migrations.Migrations[i].Number < migrations.Migrations[j].Number | ||
}) | ||
migrateCmd.PersistentFlags().StringVar(&config.Dialect, "dialect", "sqlite3", "config file") | ||
migrateCmd.PersistentFlags().StringVar(&config.DatabaseURI, "database-uri", "", "config file") | ||
|
||
a, err := app.New() | ||
if err != nil { | ||
return err | ||
} | ||
defer func() { | ||
_ = a.Close() | ||
}() | ||
|
||
// Make sure Migration table is there | ||
logrus.Debug("ensuring migrations table is present") | ||
if err := a.Database.AutoMigrate(&migrations.Migration{}).Error; err != nil { | ||
return errors.Wrap(err, "unable to automatically migrate migrations table") | ||
} | ||
_ = viper.BindPFlag("Dialect", migrateCmd.PersistentFlags().Lookup("dialect")) | ||
_ = viper.BindPFlag("DatabaseURI", migrateCmd.PersistentFlags().Lookup("database-uri")) | ||
|
||
var latest migrations.Migration | ||
if err := a.Database.Order("number desc").First(&latest).Error; err != nil && !gorm.IsRecordNotFoundError(err) { | ||
return errors.Wrap(err, "unable to find latest migration") | ||
} | ||
|
||
noMigrationsApplied := latest.Number == 0 | ||
return migrateCmd | ||
} | ||
|
||
if noMigrationsApplied && len(migrations.Migrations) == 0 { | ||
logrus.Info("no migrations to apply") | ||
return nil | ||
} | ||
func migrate(cmd *cobra.Command, app *app.App) error { | ||
number, _ := cmd.Flags().GetInt("number") | ||
dryRun, _ := cmd.Flags().GetBool("dry-run") | ||
|
||
if latest.Number >= migrations.Migrations[len(migrations.Migrations)-1].Number { | ||
logrus.Info("no migrations to apply") | ||
return nil | ||
} | ||
if dryRun { | ||
slog.Info("=== DRY RUN ===") | ||
} | ||
|
||
if number == -1 { | ||
number = int(migrations.Migrations[len(migrations.Migrations)-1].Number) | ||
} | ||
runMigrations, err := shouldRunMigrations(app, number) | ||
if err != nil { | ||
return err | ||
} | ||
if !runMigrations { | ||
return nil | ||
} | ||
|
||
if uint(number) <= latest.Number && latest.Number > 0 { | ||
logrus.Info("no migrations to apply; number is less than or equal to latest migration") | ||
return nil | ||
for _, migration := range migrations.Migrations { | ||
if migration.Number > uint(number) { | ||
break | ||
} | ||
|
||
for _, migration := range migrations.Migrations { | ||
if migration.Number > uint(number) { | ||
break | ||
} | ||
logger := slog.With("migration_number", migration.Number) | ||
logger.Info(fmt.Sprintf("applying migration %q", migration.Name)) | ||
|
||
logger := logrus.WithField("migration_number", migration.Number) | ||
logger.Infof("applying migration %q", migration.Name) | ||
|
||
if dryRun { | ||
continue | ||
} | ||
|
||
tx := a.Database.Begin() | ||
|
||
if err := migration.Forwards(tx); err != nil { | ||
logger.WithError(err).Error("unable to apply migration, rolling back") | ||
if err := tx.Rollback().Error; err != nil { | ||
logger.WithError(err).Error("unable to rollback...") | ||
} | ||
break | ||
} | ||
|
||
if err := tx.Commit().Error; err != nil { | ||
logger.WithError(err).Error("unable to commit transaction") | ||
break | ||
} | ||
|
||
if err := a.Database.Create(migration).Error; err != nil { | ||
logger.WithError(err).Error("unable to create migration record") | ||
break | ||
} | ||
if dryRun { | ||
continue | ||
} | ||
if ok := applyMigration(app, logger, migration); !ok { | ||
break | ||
} | ||
} | ||
|
||
return nil | ||
}, | ||
return nil | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(migrateCmd) | ||
func applyMigration(app *app.App, logger *slog.Logger, migration *migrations.Migration) bool { | ||
tx := app.Database.Begin() | ||
if err := migration.Forwards(tx); err != nil { | ||
logger.With("err", err).Error("unable to apply migration, rolling back") | ||
if err := tx.Rollback().Error; err != nil { | ||
logger.With("err", err).Error("unable to rollback...") | ||
} | ||
return false | ||
} | ||
|
||
if err := tx.Commit().Error; err != nil { | ||
logger.With("err", err).Error("unable to commit transaction") | ||
return false | ||
} | ||
|
||
if err := app.Database.Create(migration).Error; err != nil { | ||
logger.With("err", err).Error("unable to create migration record") | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
migrateCmd.Flags().Int("number", -1, "the migration to run forwards until; if not set, will run all migrations") | ||
migrateCmd.Flags().Bool("dry-run", false, "print out migrations to be applied without running them") | ||
func shouldRunMigrations(app *app.App, number int) (bool, error) { | ||
sort.Slice(migrations.Migrations, func(i, j int) bool { | ||
return migrations.Migrations[i].Number < migrations.Migrations[j].Number | ||
}) | ||
|
||
// Make sure Migration table is there | ||
if err := app.Database.AutoMigrate(&migrations.Migration{}).Error; err != nil { | ||
return false, errors.Wrap(err, "unable to automatically migrate migrations table") | ||
} | ||
|
||
var latest migrations.Migration | ||
if err := app.Database.Order("number desc").First(&latest).Error; err != nil && !gorm.IsRecordNotFoundError(err) { | ||
return false, errors.Wrap(err, "unable to find latest migration") | ||
} | ||
|
||
noMigrationsApplied := latest.Number == 0 | ||
if (noMigrationsApplied && len(migrations.Migrations) == 0) || | ||
(latest.Number >= migrations.Migrations[len(migrations.Migrations)-1].Number) { | ||
slog.Info("no migrations to apply") | ||
return false, nil | ||
} | ||
|
||
if number == -1 { | ||
number = int(migrations.Migrations[len(migrations.Migrations)-1].Number) | ||
} | ||
if uint(number) <= latest.Number && latest.Number > 0 { | ||
slog.Info("no migrations to apply; number is less than or equal to latest migration") | ||
return false, nil | ||
} | ||
|
||
return true, nil | ||
} |
Oops, something went wrong.