Skip to content

Commit

Permalink
fix: allow specifying empty migrations (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
bcho authored Jun 1, 2022
1 parent 0952e2c commit 59d72a9
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 7 deletions.
79 changes: 79 additions & 0 deletions fixture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,82 @@ func createTestContextWithRSATokenAuth(t testing.TB) *TestContext {
authTokenString,
)
}

type MigrationTestContext struct {
migrator *dbMigrator
db *sqlx.DB
cleanUpDB func(t testing.TB)
}

func (mtc *MigrationTestContext) Migrator() *dbMigrator {
return mtc.migrator
}

func (mtc *MigrationTestContext) CleanUp(t testing.TB) {
if mtc.cleanUpDB != nil {
mtc.cleanUpDB(t)
}
}

func NewMigrationTestContext(
t testing.TB,
migrations map[string]string,
) *MigrationTestContext {
t.Log("creating test dir")
dir, err := os.MkdirTemp("", "sqlite-rest-test")
if err != nil {
t.Fatal(err)
return nil
}

migrationsDir := filepath.Join(dir, "migrations")
if err := os.MkdirAll(migrationsDir, 0755); err != nil {
t.Fatal(err)
return nil
}

t.Log("writing migrations")
for filename, content := range migrations {
p := filepath.Join(migrationsDir, filename)
if err := os.WriteFile(p, []byte(content), 0644); err != nil {
t.Fatal(err)
return nil
}
}

t.Log("craeting in-memory db")
db, err := sqlx.Open("sqlite3", "")
if err != nil {
t.Fatal(err)
return nil
}

t.Log("creating migrator")
migratorOpts := &MigrateOptions{
Logger: createTestLogger(t).WithName("test"),
DB: db.DB,
SourceDIR: migrationsDir,
}

migrator, err := NewMigrator(migratorOpts)
if err != nil {
t.Fatal(err)
return nil
}

return &MigrationTestContext{
migrator: migrator,
db: db,
cleanUpDB: func(t testing.TB) {
if err := db.Close(); err != nil {
t.Errorf("closing in-memory db: %s", err)
return
}

if err := os.RemoveAll(dir); err != nil {
t.Fatalf("removing test dir %q: %s", dir, err)
return
}
},
}
}
54 changes: 54 additions & 0 deletions integration_migrate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package main

import (
"context"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestMigration(t *testing.T) {
t.Run("empty migrations", func(t *testing.T) {
tc := NewMigrationTestContext(t, nil)
defer tc.CleanUp(t)

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

err := tc.Migrator().Up(ctx)
assert.NoError(t, err)
})

t.Run("apply migrations", func(t *testing.T) {
tc := NewMigrationTestContext(t, map[string]string{
"1_test.up.sql": `create table test (id int);`,
"1_test.down.sql": `drop table test;`,
})
defer tc.CleanUp(t)

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

err := tc.Migrator().Up(ctx)
assert.NoError(t, err)

t.Log("rerunning migrations")
err = tc.Migrator().Up(ctx)
assert.NoError(t, err)
})

t.Run("failed migrations", func(t *testing.T) {
tc := NewMigrationTestContext(t, map[string]string{
"1_test.up.sql": `create table test invalid sql;`,
"1_test.down.sql": `drop table test;`,
})
defer tc.CleanUp(t)

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

err := tc.Migrator().Up(ctx)
assert.Error(t, err)
})
}
24 changes: 17 additions & 7 deletions migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"database/sql"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"

Expand Down Expand Up @@ -112,7 +113,6 @@ func NewMigrator(opts *MigrateOptions) (*dbMigrator, error) {
if err != nil {
return nil, err
}
fmt.Println("file://" + opts.SourceDIR)
migrator, err := migrate.NewWithDatabaseInstance(
"file://"+opts.SourceDIR,
"sqlite3", driver,
Expand All @@ -134,17 +134,27 @@ func (m *dbMigrator) Up(ctx context.Context) error {
logger.Info("applying operation")

err := m.migrator.Up()
if err == nil {
logger.Info("applied operation")

return nil
}

if errors.Is(err, migrate.ErrNoChange) {
// no update
err = nil
logger.V(8).Info("no pending migrations")
return nil
}
if err != nil {

logger.Error(err, "failed to apply operation")
return fmt.Errorf("up: %w", err)
var pathErr *fs.PathError
if errors.As(err, &pathErr) {
// no migrations set
if pathErr.Op == "first" && errors.Is(pathErr.Err, fs.ErrNotExist) {
logger.Info("no migrations to apply")
return nil
}
}
logger.Info("applied operation")

return nil
logger.Error(err, "failed to apply operation")
return fmt.Errorf("up: %w", err)
}

0 comments on commit 59d72a9

Please sign in to comment.