feat(migrate): add pending migrations function (#286)
This commit is contained in:
@@ -50,6 +50,12 @@ func TestExample(t *testing.T) {
|
|||||||
reg.Add(migrate.CallComment, "3", log)
|
reg.Add(migrate.CallComment, "3", log)
|
||||||
migrate.Callback = reg.Callback
|
migrate.Callback = reg.Callback
|
||||||
|
|
||||||
|
pending, err := migrate.Pending(context.Background(), session, cql.Files)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Pending:", err)
|
||||||
|
}
|
||||||
|
t.Log("Pending migrations:", len(pending))
|
||||||
|
|
||||||
// First run prints data
|
// First run prints data
|
||||||
if err := migrate.FromFS(context.Background(), session, cql.Files); err != nil {
|
if err := migrate.FromFS(context.Background(), session, cql.Files); err != nil {
|
||||||
t.Fatal("Migrate:", err)
|
t.Fatal("Migrate:", err)
|
||||||
|
|||||||
@@ -87,6 +87,48 @@ func List(ctx context.Context, session gocqlx.Session) ([]*Info, error) {
|
|||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pending provides a listing of pending migrations.
|
||||||
|
func Pending(ctx context.Context, session gocqlx.Session, f fs.FS) ([]*Info, error) {
|
||||||
|
applied, err := List(ctx, session)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a set of applied migration names
|
||||||
|
appliedNames := make(map[string]struct{}, len(applied))
|
||||||
|
for _, migration := range applied {
|
||||||
|
appliedNames[migration.Name] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
fm, err := fs.Glob(f, "*.cql")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("list migrations: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pending := make([]*Info, 0)
|
||||||
|
|
||||||
|
for _, name := range fm {
|
||||||
|
baseName := filepath.Base(name)
|
||||||
|
// Check if the migration is not in the applied set
|
||||||
|
if _, exists := appliedNames[baseName]; !exists {
|
||||||
|
c, err := fileChecksum(f, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("calculate checksum for %q: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
info := &Info{
|
||||||
|
Name: baseName,
|
||||||
|
StartTime: time.Now(),
|
||||||
|
Checksum: c,
|
||||||
|
}
|
||||||
|
|
||||||
|
pending = append(pending, info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pending, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ensureInfoTable(ctx context.Context, session gocqlx.Session) error {
|
func ensureInfoTable(ctx context.Context, session gocqlx.Session) error {
|
||||||
return session.ContextQuery(ctx, infoSchema, nil).ExecRelease()
|
return session.ContextQuery(ctx, infoSchema, nil).ExecRelease()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,54 @@ func recreateTables(tb testing.TB, session gocqlx.Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPending(t *testing.T) {
|
||||||
|
session := gocqlxtest.CreateSession(t)
|
||||||
|
defer session.Close()
|
||||||
|
recreateTables(t, session)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
t.Run("pending", func(t *testing.T) {
|
||||||
|
defer recreateTables(t, session)
|
||||||
|
|
||||||
|
f := memfs.New()
|
||||||
|
writeFile(f, 0, fmt.Sprintf(insertMigrate, 0)+";")
|
||||||
|
|
||||||
|
pending, err := migrate.Pending(ctx, session, f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(pending) != 1 {
|
||||||
|
t.Fatal("expected 2 pending migrations got", len(pending))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = migrate.FromFS(ctx, session, f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pending, err = migrate.Pending(ctx, session, f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(pending) != 0 {
|
||||||
|
t.Fatal("expected no pending migrations got", len(pending))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i < 3; i++ {
|
||||||
|
writeFile(f, i, fmt.Sprintf(insertMigrate, i)+";")
|
||||||
|
}
|
||||||
|
|
||||||
|
pending, err = migrate.Pending(ctx, session, f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(pending) != 2 {
|
||||||
|
t.Fatal("expected 2 pending migrations got", len(pending))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestMigration(t *testing.T) {
|
func TestMigration(t *testing.T) {
|
||||||
session := gocqlxtest.CreateSession(t)
|
session := gocqlxtest.CreateSession(t)
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|||||||
Reference in New Issue
Block a user