Skip to content

Commit 98099ce

Browse files
authored
Feat/run migration (#1303)
* feat: add RunMigration method * .
1 parent c951ef4 commit 98099ce

File tree

2 files changed

+99
-1
lines changed

2 files changed

+99
-1
lines changed

internal/dbtest/migrate_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ func TestMigrate(t *testing.T) {
5555
tests := []Test{
5656
{run: testMigrateUpAndDown},
5757
{run: testMigrateUpError},
58+
{run: testRunMigration},
5859
}
5960

6061
testEachDB(t, func(t *testing.T, dbName string, db *bun.DB) {
@@ -180,6 +181,64 @@ func testMigrateUpError(t *testing.T, db *bun.DB) {
180181
require.Equal(t, []string{"down2", "down1"}, history)
181182
}
182183

184+
func testRunMigration(t *testing.T, db *bun.DB) {
185+
ctx := context.Background()
186+
cleanupMigrations(t, ctx, db)
187+
188+
var history []string
189+
190+
migrations := migrate.NewMigrations()
191+
migrations.Add(migrate.Migration{
192+
Name: "20060102150405",
193+
Up: func(ctx context.Context, migrator *migrate.Migrator, migration *migrate.Migration) error {
194+
history = append(history, "up1")
195+
return nil
196+
},
197+
})
198+
migrations.Add(migrate.Migration{
199+
Name: "20060102160405",
200+
Up: func(ctx context.Context, migrator *migrate.Migrator, migration *migrate.Migration) error {
201+
history = append(history, "up2")
202+
return nil
203+
},
204+
})
205+
206+
m := migrate.NewMigrator(db, migrations,
207+
migrate.WithTableName(migrationsTable),
208+
migrate.WithLocksTableName(migrationLocksTable),
209+
)
210+
require.NoError(t, m.Reset(ctx))
211+
212+
_, err := m.Migrate(ctx)
213+
require.NoError(t, err)
214+
require.Equal(t, []string{"up1", "up2"}, history)
215+
216+
appliedBefore, err := m.AppliedMigrations(ctx)
217+
require.NoError(t, err)
218+
migrationIDs := func(ms migrate.MigrationSlice) []int64 {
219+
ids := make([]int64, len(ms))
220+
for i := range ms {
221+
ids[i] = ms[i].ID
222+
}
223+
return ids
224+
}
225+
migrationsWithStatus, err := m.MigrationsWithStatus(ctx)
226+
require.NoError(t, err)
227+
require.Len(t, migrationsWithStatus, 2)
228+
229+
targetID := migrationsWithStatus[0].ID
230+
require.NotZero(t, targetID)
231+
232+
history = nil
233+
err = m.RunMigration(ctx, targetID)
234+
require.NoError(t, err)
235+
require.Equal(t, []string{"up1"}, history)
236+
237+
appliedAfter, err := m.AppliedMigrations(ctx)
238+
require.NoError(t, err)
239+
require.ElementsMatch(t, migrationIDs(appliedBefore), migrationIDs(appliedAfter))
240+
}
241+
183242
// newAutoMigratorOrSkip creates an AutoMigrator configured to use test migratins/locks
184243
// tables and dedicated migrations directory. If an AutoMigrator cannob be created because
185244
// the dialect doesn't support either schema inspections or migrations, the test will be *skipped*

migrate/migrator.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,45 @@ func (m *Migrator) Migrate(ctx context.Context, opts ...MigrationOption) (*Migra
207207
return group, nil
208208
}
209209

210+
// RunMigration runs the up migration with the given ID without marking it as applied.
211+
// It runs the migration even if it is already marked as applied.
212+
func (m *Migrator) RunMigration(
213+
ctx context.Context, migrationID int64, opts ...MigrationOption,
214+
) error {
215+
cfg := newMigrationConfig(opts)
216+
217+
if err := m.validate(); err != nil {
218+
return err
219+
}
220+
if migrationID == 0 {
221+
return errors.New("migrate: migration id must be greater than zero")
222+
}
223+
224+
migrations, _, err := m.migrationsWithStatus(ctx)
225+
if err != nil {
226+
return err
227+
}
228+
229+
var migration *Migration
230+
for i := range migrations {
231+
if migrations[i].ID == migrationID {
232+
migration = &migrations[i]
233+
break
234+
}
235+
}
236+
if migration == nil {
237+
return fmt.Errorf("migrate: migration with id %d not found", migrationID)
238+
}
239+
if migration.Up == nil {
240+
return fmt.Errorf("migrate: migration %s does not have up migration", migration.Name)
241+
}
242+
if cfg.nop {
243+
return nil
244+
}
245+
246+
return migration.Up(ctx, m, migration)
247+
}
248+
210249
func (m *Migrator) Rollback(ctx context.Context, opts ...MigrationOption) (*MigrationGroup, error) {
211250
cfg := newMigrationConfig(opts)
212251

@@ -418,7 +457,7 @@ func (m *Migrator) MissingMigrations(ctx context.Context) (MigrationSlice, error
418457
return applied, nil
419458
}
420459

421-
// AppliedMigrations selects applied (applied) migrations in descending order.
460+
// AppliedMigrations returns applied (applied) migrations in descending order.
422461
func (m *Migrator) AppliedMigrations(ctx context.Context) (MigrationSlice, error) {
423462
var ms MigrationSlice
424463
if err := m.db.NewSelect().

0 commit comments

Comments
 (0)