// Command migrate 是 visionA-backend 的獨立 migration 工具。 // // DB 接入塊 0:提供「不啟動整個 api-server 也能跑 migration」的入口, // 供 CI / 部署流程 / 手動操作使用。api-server 啟動時的 auto-migrate(VISIONA_DB_AUTO_MIGRATE) // 與本工具共用同一份嵌入式 migration(migrations.FS)+ internal/db.Migrator,行為一致。 // // 用法: // // go run ./cmd/migrate up # 套用所有未執行的 migration(預設) // go run ./cmd/migrate down # 回退一個版本 // go run ./cmd/migrate version # 顯示目前 schema 版本 // // 連線資訊一律走 VISIONA_DB_* 環境變數(與 api-server 相同),不接受密碼當 CLI 參數 // (避免密碼出現在 shell history / process list)。 package main import ( "fmt" "os" "visiona-backend/internal/config" "visiona-backend/internal/db" "visiona-backend/internal/logger" ) func main() { cfg := config.Load() log := logger.New(cfg.Logger.Level).With("service", "migrate") if !cfg.Database.Enabled() { log.Error("database not configured", "hint", "set VISIONA_DB_HOST + VISIONA_DB_USER + VISIONA_DB_NAME") os.Exit(1) } cmd := "up" if len(os.Args) > 1 { cmd = os.Args[1] } mg, err := db.NewMigrator(cfg.Database, log) if err != nil { log.Error("failed to init migrator", "error", err, "target", db.SafeTarget(cfg.Database)) os.Exit(1) } defer func() { if cerr := mg.Close(); cerr != nil { log.Warn("migrator close error", "error", cerr) } }() switch cmd { case "up": if err := mg.Up(); err != nil { log.Error("migrate up failed", "error", err) os.Exit(1) } log.Info("migrate up complete", "target", db.SafeTarget(cfg.Database)) case "down": if err := mg.Down(); err != nil { log.Error("migrate down failed", "error", err) os.Exit(1) } log.Info("migrate down (one step) complete", "target", db.SafeTarget(cfg.Database)) case "version": ver, dirty, err := mg.Version() if err != nil { log.Error("read version failed", "error", err) os.Exit(1) } log.Info("schema version", "version", ver, "dirty", dirty) default: fmt.Fprintf(os.Stderr, "unknown command %q; use one of: up | down | version\n", cmd) os.Exit(2) } }