From 862b448ab8cb6fcd97e34a2f57ef835334415d96 Mon Sep 17 00:00:00 2001 From: Mike Fridman Date: Sun, 10 Dec 2023 14:55:32 -0500 Subject: [PATCH 1/4] Improve provider apply errors --- provider.go | 12 ++++++++++-- provider_errors.go | 15 +++++++++++---- provider_run_test.go | 14 ++++++++++++++ provider_types.go | 19 ++++++++++++++++++- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/provider.go b/provider.go index e7870caeb..80183418d 100644 --- a/provider.go +++ b/provider.go @@ -409,8 +409,16 @@ func (p *Provider) apply( if err != nil && !errors.Is(err, database.ErrVersionNotFound) { return nil, err } - // If the migration has already been applied, return an error. But, if the migration is being - // rolled back, we allow the individual migration to be applied again. + // There are a few states here: + // 1. direction is up + // a. migration is applied, this is an error (ErrAlreadyApplied) + // b. migration is not applied, apply it + // 2. direction is down + // a. migration is applied, rollback + // b. migration is not applied, this is an error (ErrNotApplied) + if result == nil && !direction { + return nil, fmt.Errorf("version %d: %w", version, ErrNotApplied) + } if result != nil && direction { return nil, fmt.Errorf("version %d: %w", version, ErrAlreadyApplied) } diff --git a/provider_errors.go b/provider_errors.go index 72c8d672c..fdcc3b5af 100644 --- a/provider_errors.go +++ b/provider_errors.go @@ -6,15 +6,22 @@ import ( ) var ( - // ErrVersionNotFound when a migration version is not found. + // ErrVersionNotFound is returned when a specific migration version is not located. + // This can occur if a corresponding .sql file or a Go migration function for the + // specified version is missing. ErrVersionNotFound = errors.New("version not found") - // ErrAlreadyApplied when a migration has already been applied. - ErrAlreadyApplied = errors.New("already applied") - // ErrNoMigrations is returned by [NewProvider] when no migrations are found. ErrNoMigrations = errors.New("no migrations found") + // ErrAlreadyApplied indicates that the migration cannot be applied because it has already been + // executed. This error is returned by [Provider.Apply]. + ErrAlreadyApplied = errors.New("migration already applied") + + // ErrNotApplied indicates that the rollback cannot be performed because the migration has not + // yet been applied. This error is returned by [Provider.Apply]. + ErrNotApplied = errors.New("migration not applied") + // errInvalidVersion is returned when a migration version is invalid. errInvalidVersion = errors.New("version must be greater than 0") ) diff --git a/provider_run_test.go b/provider_run_test.go index e6926ea16..cb07c0116 100644 --- a/provider_run_test.go +++ b/provider_run_test.go @@ -765,6 +765,20 @@ func TestCustomStoreTableExists(t *testing.T) { check.NoError(t, err) } +func TestProviderApply(t *testing.T) { + t.Parallel() + + ctx := context.Background() + p, err := goose.NewProvider(goose.DialectSQLite3, newDB(t), newFsys()) + check.NoError(t, err) + _, err = p.ApplyVersion(ctx, 1, true) + check.NoError(t, err) + // This version has a corresponding down migration, but has never been applied. + _, err = p.ApplyVersion(ctx, 2, false) + check.HasError(t, err) + check.Bool(t, errors.Is(err, goose.ErrNotApplied), true) +} + type customStoreSQLite3 struct { database.Store } diff --git a/provider_types.go b/provider_types.go index 1b4983b2b..d8bef1673 100644 --- a/provider_types.go +++ b/provider_types.go @@ -1,6 +1,10 @@ package goose -import "time" +import ( + "fmt" + "path/filepath" + "time" +) // MigrationType is the type of migration. type MigrationType string @@ -32,6 +36,19 @@ type MigrationResult struct { Error error } +func (m *MigrationResult) String() string { + state := "OK" + if m.Empty { + state = "EMPTY" + } + return fmt.Sprintf("%-6s %-4s %s (%s)", + state, + m.Direction, + filepath.Base(m.Source.Path), + truncateDuration(m.Duration), + ) +} + // State represents the state of a migration. type State string From 8a0319a8a3aefaf37ea65d9ac9788c305049815b Mon Sep 17 00:00:00 2001 From: Mike Fridman Date: Sun, 10 Dec 2023 14:55:47 -0500 Subject: [PATCH 2/4] comment --- provider_errors.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/provider_errors.go b/provider_errors.go index fdcc3b5af..82ba2c86b 100644 --- a/provider_errors.go +++ b/provider_errors.go @@ -6,9 +6,9 @@ import ( ) var ( - // ErrVersionNotFound is returned when a specific migration version is not located. - // This can occur if a corresponding .sql file or a Go migration function for the - // specified version is missing. + // ErrVersionNotFound is returned when a specific migration version is not located. This can + // occur if a corresponding .sql file or a Go migration function for the specified version is + // missing. ErrVersionNotFound = errors.New("version not found") // ErrNoMigrations is returned by [NewProvider] when no migrations are found. From d6ecc51fc467a468ab0a01358b0fc58d7b9ef10f Mon Sep 17 00:00:00 2001 From: Mike Fridman Date: Sun, 10 Dec 2023 15:01:59 -0500 Subject: [PATCH 3/4] fmt --- provider_errors.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/provider_errors.go b/provider_errors.go index 82ba2c86b..79a2cda2b 100644 --- a/provider_errors.go +++ b/provider_errors.go @@ -7,8 +7,7 @@ import ( var ( // ErrVersionNotFound is returned when a specific migration version is not located. This can - // occur if a corresponding .sql file or a Go migration function for the specified version is - // missing. + // occur if a .sql file or a Go migration function for the specified version is missing. ErrVersionNotFound = errors.New("version not found") // ErrNoMigrations is returned by [NewProvider] when no migrations are found. From 2e5a92605eb434d61f0327602fd667c26470c743 Mon Sep 17 00:00:00 2001 From: Mike Fridman Date: Sun, 10 Dec 2023 15:03:19 -0500 Subject: [PATCH 4/4] fix test error --- provider_run_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider_run_test.go b/provider_run_test.go index cb07c0116..efa8d7091 100644 --- a/provider_run_test.go +++ b/provider_run_test.go @@ -262,7 +262,7 @@ func TestProviderRun(t *testing.T) { _, err = p.ApplyVersion(ctx, 1, true) check.HasError(t, err) check.Bool(t, errors.Is(err, goose.ErrAlreadyApplied), true) - check.Contains(t, err.Error(), "version 1: already applied") + check.Contains(t, err.Error(), "version 1: migration already applied") }) t.Run("status", func(t *testing.T) { ctx := context.Background()