Files
job-search/internal/cli/migrate/status.go
T
bwilliams e19c8c2b69 Imports split into three groups: standard library, third-party, then this project's own packages
gci is configured with the sections standard, default and localmodule, and
goimports with the module path as its local prefix, so both formatters
agree.
2026-10-14 17:40:06 +01:00

96 lines
2.3 KiB
Go

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)
},
}
}