feat(migrate): add lifecycle commands and standalone authoring
This commit is contained in:
1 parent
3cd3f49c11
commit
2727ac83db
12 files changed
+1553
-31
No files matched your search
+90
@@ -0,0 +1,90 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user