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, out io.Writer, migrator *goose.Provider, ) error { statuses, err := migrator.Status(ctx) if err != nil { return err } current, err := migrator.GetDBVersion(ctx) if err != nil { return err } latest := store.LatestVersion(migrator) pending := 0 for _, status := range statuses { if status.State == goose.StatePending { pending++ } } output := &errWriter{ out: out, } switch { case current > latest: output.printf( "Database version %d is newer than this build (latest %d)\n", current, latest, ) case pending == 0: output.printf("Database version %d of %d (up-to-date)\n", current, latest) default: output.printf( "Database version %d of %d (%d pending)\n", current, latest, pending, ) } if output.err != nil { return output.err } table := tabwriter.NewWriter(out, 0, 0, 2, ' ', 0) output = &errWriter{ out: table, } for _, status := range statuses { applied := "" if status.State == goose.StateApplied { applied = status.AppliedAt.Local().Format("2006-01-02 15:04:05") } output.printf( " %d\t%s\t%s\t%s\n", status.Source.Version, status.State, applied, filepath.Base(status.Source.Path), ) } return errors.Join(output.err, table.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("command persistent pre-run", "command", "migrate.status") }, PersistentPostRun: func(cmd *cobra.Command, args []string) { slog.Debug("command persistent post-run", "command", "migrate.status") }, RunE: func(cmd *cobra.Command, args []string) (err error) { slog.Debug("command run", "command", "migrate.status") migrator, db, err := openMigrator(cmd, opts, false, false) if err != nil { return err } defer closeDB(db, &err) return printStatus(cmd.Context(), cmd.OutOrStdout(), migrator) }, } }