Skip to content

Commit 65176ff

Browse files
committed
tapd: allow migration target version to be specified
This commit allows us to either run all migrations or up to a given version on the respective stores. This will enable us to test individual migration steps in unit tests.
1 parent 8769305 commit 65176ff

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

tapdb/migrations.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tapdb
22

33
import (
44
"bytes"
5+
"errors"
56
"io"
67
"io/fs"
78
"net/http"
@@ -12,11 +13,31 @@ import (
1213
"github.com/golang-migrate/migrate/v4/source/httpfs"
1314
)
1415

15-
// applyMigrations executes all database migration files found in the given file
16+
// MigrationTarget is a functional option that can be passed to applyMigrations
17+
// to specify a target version to migrate to.
18+
type MigrationTarget func(mig *migrate.Migrate) error
19+
20+
var (
21+
// TargetLatest is a MigrationTarget that migrates to the latest
22+
// version available.
23+
TargetLatest = func(mig *migrate.Migrate) error {
24+
return mig.Up()
25+
}
26+
27+
// TargetVersion is a MigrationTarget that migrates to the given
28+
// version.
29+
TargetVersion = func(version uint) MigrationTarget {
30+
return func(mig *migrate.Migrate) error {
31+
return mig.Migrate(version)
32+
}
33+
}
34+
)
35+
36+
// applyMigrations executes database migration files found in the given file
1637
// system under the given path, using the passed database driver and database
17-
// name.
18-
func applyMigrations(fs fs.FS, driver database.Driver, path,
19-
dbName string) error {
38+
// name, up to or down to the given target version.
39+
func applyMigrations(fs fs.FS, driver database.Driver, path, dbName string,
40+
targetVersion MigrationTarget) error {
2041

2142
// With the migrate instance open, we'll create a new migration source
2243
// using the embedded file system stored in sqlSchemas. The library
@@ -36,8 +57,10 @@ func applyMigrations(fs fs.FS, driver database.Driver, path,
3657
if err != nil {
3758
return err
3859
}
39-
err = sqlMigrate.Up()
40-
if err != nil && err != migrate.ErrNoChange {
60+
61+
// Execute the migration based on the target given.
62+
err = targetVersion(sqlMigrate)
63+
if err != nil && !errors.Is(err, migrate.ErrNoChange) {
4164
return err
4265
}
4366

tapdb/postgres.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func NewPostgresStore(cfg *PostgresConfig) (*PostgresStore, error) {
129129
// Now that the database is open, populate the database with our set of
130130
// schemas based on our embedded in-memory file system.
131131
if !cfg.SkipMigrations {
132-
if err := s.ExecuteMigrations(); err != nil {
132+
if err := s.ExecuteMigrations(TargetLatest); err != nil {
133133
return nil, fmt.Errorf("error executing migrations: "+
134134
"%w", err)
135135
}
@@ -138,8 +138,9 @@ func NewPostgresStore(cfg *PostgresConfig) (*PostgresStore, error) {
138138
return s, nil
139139
}
140140

141-
// ExecuteMigrations runs all migrations for the Postgres database.
142-
func (s *PostgresStore) ExecuteMigrations() error {
141+
// ExecuteMigrations runs migrations for the Postgres database, depending on the
142+
// target given, either all migrations or up to a given version.
143+
func (s *PostgresStore) ExecuteMigrations(target MigrationTarget) error {
143144
driver, err := postgres_migrate.WithInstance(
144145
s.DB, &postgres_migrate.Config{},
145146
)
@@ -149,7 +150,7 @@ func (s *PostgresStore) ExecuteMigrations() error {
149150

150151
postgresFS := newReplacerFS(sqlSchemas, postgresSchemaReplacements)
151152
return applyMigrations(
152-
postgresFS, driver, "sqlc/migrations", s.cfg.DBName,
153+
postgresFS, driver, "sqlc/migrations", s.cfg.DBName, target,
153154
)
154155
}
155156

tapdb/sqlite.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func NewSqliteStore(cfg *SqliteConfig) (*SqliteStore, error) {
140140
// Now that the database is open, populate the database with our set of
141141
// schemas based on our embedded in-memory file system.
142142
if !cfg.SkipMigrations {
143-
if err := s.ExecuteMigrations(); err != nil {
143+
if err := s.ExecuteMigrations(TargetLatest); err != nil {
144144
return nil, fmt.Errorf("error executing migrations: "+
145145
"%w", err)
146146
}
@@ -149,8 +149,9 @@ func NewSqliteStore(cfg *SqliteConfig) (*SqliteStore, error) {
149149
return s, nil
150150
}
151151

152-
// ExecuteMigrations executes all the migrations for the sqlite database.
153-
func (s *SqliteStore) ExecuteMigrations() error {
152+
// ExecuteMigrations runs migrations for the sqlite database, depending on the
153+
// target given, either all migrations or up to a given version.
154+
func (s *SqliteStore) ExecuteMigrations(target MigrationTarget) error {
154155
driver, err := sqlite_migrate.WithInstance(
155156
s.DB, &sqlite_migrate.Config{},
156157
)
@@ -159,7 +160,9 @@ func (s *SqliteStore) ExecuteMigrations() error {
159160
}
160161

161162
sqliteFS := newReplacerFS(sqlSchemas, sqliteSchemaReplacements)
162-
return applyMigrations(sqliteFS, driver, "sqlc/migrations", "sqlite")
163+
return applyMigrations(
164+
sqliteFS, driver, "sqlc/migrations", "sqlite", target,
165+
)
163166
}
164167

165168
// NewTestSqliteDB is a helper function that creates an SQLite database for

0 commit comments

Comments
 (0)