mirror of https://github.com/pressly/goose.git
feat: Gracefully recover Go migrations that panic (#643)
parent
9e6ef20c4f
commit
1e40462848
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -424,7 +425,13 @@ func runMigration(ctx context.Context, db database.DBTxConn, m *Migration, direc
|
|||
|
||||
// runGo is a helper function that runs the given Go functions in the given direction. It must only
|
||||
// be called after the migration has been initialized.
|
||||
func runGo(ctx context.Context, db database.DBTxConn, m *Migration, direction bool) error {
|
||||
func runGo(ctx context.Context, db database.DBTxConn, m *Migration, direction bool) (retErr error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
retErr = fmt.Errorf("panic: %v\n%s", r, debug.Stack())
|
||||
}
|
||||
}()
|
||||
|
||||
switch db := db.(type) {
|
||||
case *sql.Conn:
|
||||
return fmt.Errorf("go migrations are not supported with *sql.Conn")
|
||||
|
|
|
@ -724,6 +724,34 @@ func TestSQLiteSharedCache(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestGoMigrationPanic(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
const (
|
||||
wantErrString = "panic: runtime error: index out of range [7] with length 0"
|
||||
)
|
||||
migration := goose.NewGoMigration(
|
||||
1,
|
||||
&goose.GoFunc{RunTx: func(ctx context.Context, tx *sql.Tx) error {
|
||||
var ss []int
|
||||
_ = ss[7]
|
||||
return nil
|
||||
}},
|
||||
nil,
|
||||
)
|
||||
p, err := goose.NewProvider(goose.DialectSQLite3, newDB(t), nil,
|
||||
goose.WithGoMigrations(migration), // Add a Go migration that panics.
|
||||
)
|
||||
check.NoError(t, err)
|
||||
_, err = p.Up(ctx)
|
||||
check.HasError(t, err)
|
||||
check.Contains(t, err.Error(), wantErrString)
|
||||
var expected *goose.PartialError
|
||||
check.Bool(t, errors.As(err, &expected), true)
|
||||
check.Contains(t, expected.Err.Error(), wantErrString)
|
||||
}
|
||||
|
||||
func TestCustomStoreTableExists(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
Loading…
Reference in New Issue