// Command consumer verifies generated registrations and the production boundary. package main import ( "context" "database/sql" "embed" "fmt" "io" "log/slog" "os" "example.com/consumer/migrations" "github.com/pressly/goose/v3" urfavecli "github.com/urfave/cli/v3" "go.auvem.com/corestack/lifecycle" "go.auvem.com/corestack/lifecycle/cli" "go.auvem.com/corestack/migrate" adapter "go.auvem.com/corestack/migrate/lifecycle" _ "modernc.org/sqlite" ) //go:embed migrations var files embed.FS func main() { ctx := context.Background() logger := slog.New(slog.NewTextHandler(io.Discard, nil)) var db *sql.DB dbModule := lifecycle.Module{Name: "database", Setup: func(context.Context) error { var err error; db, err = sql.Open("sqlite", os.Args[1]); return err }, Teardown: func(context.Context) error { return db.Close() }} resolver := func(context.Context) (*goose.Provider, error) { return migrate.New(db, goose.DialectSQLite3, files, "migrations", logger, migrations.GoMigrations()...) } root := &urfavecli.Command{Name: "consumer", Commands: []*urfavecli.Command{adapter.Commands(lifecycle.Config{Logger: logger}, []lifecycle.Module{dbModule}, resolver)}} code, err := cli.Run(ctx, root, []string{"consumer", "migrate", "up"}) must(err) if code != 0 { panic(code) } db, err = sql.Open("sqlite", os.Args[1]) must(err) defer db.Close() p, err := resolver(ctx) must(err) version, err := p.GetDBVersion(ctx) must(err) if version != 4 { panic(version) } pending, err := p.HasPending(ctx) must(err) if pending { panic("pending after apply") } statuses, err := p.Status(ctx) must(err) if len(statuses) != 4 { panic(len(statuses)) } for i, status := range statuses { if status.Source.Version != int64(i+1) || status.State != goose.StateApplied { panic(status) } } a, b := migrations.GoMigrations(), migrations.GoMigrations() if len(a) != 3 || len(b) != 3 { panic("missing safe-suffix Go migrations") } for i := range a { if a[i] == b[i] || a[i].Version != int64(i+2) || b[i].Version != int64(i+2) { panic("registration/version isolation") } } isolatedDB, err := sql.Open("sqlite", ":memory:") must(err) defer isolatedDB.Close() isolated, err := migrate.New(isolatedDB, goose.DialectSQLite3, files, "migrations", logger, migrations.GoMigrations()...) must(err) pending, err = isolated.HasPending(ctx) must(err) if !pending { panic("provider isolation") } fmt.Println("version=4 pending=false versions=1,2,3,4 fresh=true isolated-pending=true") } func must(err error) { if err != nil { panic(err) } }