Skip to content

Commit

Permalink
Refactoring commands and configs as well update linters
Browse files Browse the repository at this point in the history
  • Loading branch information
javaducky committed May 19, 2024
1 parent f353066 commit 20826ee
Show file tree
Hide file tree
Showing 18 changed files with 349 additions and 296 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Install Go(lang)
uses: actions/setup-go@v5
with:
go-version: 1.21.x
go-version: 1.22.x
- name: Run unit tests
run: go test -test.short -v -cover -race ./...

Expand All @@ -29,14 +29,14 @@ jobs:
- name: Install Go(lang)
uses: actions/setup-go@v5
with:
go-version: 1.21.x
go-version: 1.22.x
- name: Build server binary
run: |
go version
make build-only
- name: Install k6
run: |
curl https://github.com/grafana/k6/releases/download/v0.48.0/k6-v0.48.0-linux-amd64.tar.gz -L | tar xvz --strip-components 1
curl https://github.com/grafana/k6/releases/download/v0.51.0/k6-v0.51.0-linux-amd64.tar.gz -L | tar xvz --strip-components 1
- name: k6 Compliance
run: |
echo "DatabaseURI: "${GITHUB_WORKSPACE}/gorm.db"" > config.yaml
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Install Go(lang)
uses: actions/setup-go@v5
with:
go-version: 1.21.x
go-version: 1.22.x
- name: Check module dependencies
run: |
go version
Expand All @@ -30,7 +30,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.21.x
go-version: 1.22.x
- name: Retrieve golangci-lint version
run: |
echo "Version=$(head -n 1 "${GITHUB_WORKSPACE}/.golangci.yml" | tr -d '# ')" >> $GITHUB_OUTPUT
Expand Down
14 changes: 11 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# v1.55.2
# v1.58.2
# Please don't remove the first line. It is used in CI to determine the golangci-lint version.
run:
timeout: 5m
Expand All @@ -12,13 +12,21 @@ issues:
- gocognit
- funlen
- lll
- path: (cmd|env|migrations)\/
- path: (env|migrations)\/
linters:
- gochecknoglobals

linters-settings:
errcheck:
check-type-assertsions: true
disable-default-exclusions: true
exclude-functions:
- io/ioutil.ReadFile
- io.Copy(*bytes.Buffer)
- io.Copy(os.Stdout)
govet:
check-shadowing: true
enable:
shadow
funlen:
lines: 80
statements: 60
Expand Down
188 changes: 106 additions & 82 deletions cmd/migrate.go
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
}
Loading

0 comments on commit 20826ee

Please sign in to comment.