@@ -11,13 +11,15 @@ import (
1111 "path/filepath"
1212 "regexp"
1313 "runtime"
14+ "slices"
1415 "sort"
1516 "strconv"
1617 "time"
1718
1819 "github.com/uptrace/bun"
1920
2021 "github.com/getpatchwork/patchwork/pkg/db"
22+ "github.com/getpatchwork/patchwork/pkg/log"
2123)
2224
2325type MigrationFunc func (ctx context.Context , tx bun.Tx ) error
@@ -64,7 +66,7 @@ func Register(up, down MigrationFunc) {
6466 })
6567}
6668
67- type schemaMigration struct {
69+ type SchemaMigration struct {
6870 bun.BaseModel `bun:"table:schema_migrations"`
6971 Num int `bun:"num,pk"`
7072 Name string `bun:"name,notnull"`
@@ -73,15 +75,15 @@ type schemaMigration struct {
7375
7476func ensureTable (ctx context.Context , database bun.IDB ) error {
7577 _ , err := database .NewCreateTable ().
76- Model ((* schemaMigration )(nil )).
78+ Model ((* SchemaMigration )(nil )).
7779 IfNotExists ().
7880 Exec (ctx )
7981 return err
8082}
8183
8284func lastApplied (ctx context.Context , database * bun.DB ) (int , error ) {
8385 var num int
84- err := database .NewSelect ().Model ((* schemaMigration )(nil )).
86+ err := database .NewSelect ().Model ((* SchemaMigration )(nil )).
8587 ColumnExpr ("COALESCE(MAX(num), 0)" ).
8688 Scan (ctx , & num )
8789 return num , err
@@ -96,6 +98,22 @@ func sorted() []Migration {
9698 return out
9799}
98100
101+ func ListMigrations (ctx context.Context , database * bun.DB ) []SchemaMigration {
102+ var out []SchemaMigration
103+
104+ // first get all applied from DB (ignore errors)
105+ database .NewSelect ().Model (& out ).OrderExpr ("num ASC" ).Scan (ctx )
106+
107+ for _ , m := range sorted () {
108+ if ! slices .ContainsFunc (out , func (s SchemaMigration ) bool { return s .Num == m .Num }) {
109+ // then, fill in unapplied ones (AppliedAt will be zero)
110+ out = append (out , SchemaMigration {Num : m .Num , Name : m .Name })
111+ }
112+ }
113+
114+ return out
115+ }
116+
99117func RunMigrations (ctx context.Context , database * bun.DB ) error {
100118 if ! tableExists (ctx , database , "schema_migrations" ) {
101119 return bootstrap (ctx , database )
@@ -118,6 +136,8 @@ func RunMigrations(ctx context.Context, database *bun.DB) error {
118136 continue
119137 }
120138
139+ log .Noticef ("Running database migration %s" , m .Name )
140+
121141 tx , err := database .BeginTx (ctx , nil )
122142 if err != nil {
123143 return fmt .Errorf ("%s: begin tx: %w" , m .Name , err )
@@ -128,7 +148,7 @@ func RunMigrations(ctx context.Context, database *bun.DB) error {
128148 return fmt .Errorf ("%s: %w" , m .Name , err )
129149 }
130150
131- if _ , err := tx .NewInsert ().Model (& schemaMigration {
151+ if _ , err := tx .NewInsert ().Model (& SchemaMigration {
132152 Num : m .Num ,
133153 Name : m .Name ,
134154 AppliedAt : time .Now (),
@@ -182,7 +202,7 @@ func Rollback(ctx context.Context, database *bun.DB) error {
182202 return fmt .Errorf ("%s: %w" , last .Name , err )
183203 }
184204
185- if _ , err := tx .NewDelete ().Model ((* schemaMigration )(nil )).
205+ if _ , err := tx .NewDelete ().Model ((* SchemaMigration )(nil )).
186206 Where ("num = ?" , last .Num ).Exec (ctx ); err != nil {
187207 _ = tx .Rollback ()
188208 return fmt .Errorf ("%s: remove record: %w" , last .Name , err )
@@ -224,7 +244,7 @@ func bootstrap(ctx context.Context, database *bun.DB) error {
224244 }
225245
226246 for _ , m := range sorted () {
227- if _ , err := tx .NewInsert ().Model (& schemaMigration {
247+ if _ , err := tx .NewInsert ().Model (& SchemaMigration {
228248 Num : m .Num ,
229249 Name : m .Name ,
230250 AppliedAt : time .Now (),
0 commit comments