package migrate import ( "context" "errors" "io" "log/slog" "path/filepath" "text/tabwriter" "github.com/pressly/goose/v3" "github.com/spf13/cobra" "git.avsdev.uk/Go/job-search/internal/cli" "git.avsdev.uk/Go/job-search/internal/store" ) // printStatus lists every migration as applied (with when) or pending, // after a summary line, e.g. // // Database version 4 of 6 (2 pending) // 1 applied 2026-10-07 10:12:01 00001_create_opportunities_table.sql // ... // 5 pending 00005_create_opportunity_classifications_table.sql func printStatus(ctx context.Context, w io.Writer, m *goose.Provider) error { statuses, err := m.Status(ctx) if err != nil { return err } current, err := m.GetDBVersion(ctx) if err != nil { return err } latest := store.LatestVersion(m) pending := 0 for _, s := range statuses { if s.State == goose.StatePending { pending++ } } ew := &errWriter{w: w} switch { case current > latest: ew.printf("Database version %d is newer than this build (latest %d)\n", current, latest) case pending == 0: ew.printf("Database version %d of %d (up-to-date)\n", current, latest) default: ew.printf("Database version %d of %d (%d pending)\n", current, latest, pending) } if ew.err != nil { return ew.err } tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0) ew = &errWriter{w: tw} for _, s := range statuses { applied := "" if s.State == goose.StateApplied { applied = s.AppliedAt.Local().Format("2006-01-02 15:04:05") } ew.printf(" %d\t%s\t%s\t%s\n", s.Source.Version, s.State, applied, filepath.Base(s.Source.Path)) } return errors.Join(ew.err, tw.Flush()) } func commandStatus(opts *cli.Options) *cobra.Command { return &cobra.Command{ Use: "status", Short: "Show which migrations have been applied to the SQLite database", Args: cobra.NoArgs, PersistentPreRun: func(cmd *cobra.Command, args []string) { slog.Debug("migrate.status.PersistentPreRun") }, PersistentPostRun: func(cmd *cobra.Command, args []string) { slog.Debug("migrate.status.PersistentPostRun") }, RunE: func(cmd *cobra.Command, args []string) (err error) { slog.Debug("migrate.status.Run") m, db, err := openMigrator(cmd, opts, false, false) if err != nil { return err } defer closeDB(db, &err) return printStatus(cmd.Context(), cmd.OutOrStdout(), m) }, } }