• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / cli / 12941917448

24 Jan 2025 02:14AM UTC coverage: 58.238% (-0.05%) from 58.292%
12941917448

Pull #3046

github

web-flow
Merge 322044b46 into 337aacd0d
Pull Request #3046: feat(cli): add repeatable migrations

25 of 48 new or added lines in 4 files covered. (52.08%)

6 existing lines in 2 files now uncovered.

7617 of 13079 relevant lines covered (58.24%)

202.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.74
/pkg/migration/list.go
1
package migration
2

3
import (
4
        "context"
5
        "fmt"
6
        "io/fs"
7
        "os"
8
        "path/filepath"
9
        "regexp"
10
        "strconv"
11

12
        "github.com/go-errors/errors"
13
        "github.com/jackc/pgconn"
14
        "github.com/jackc/pgerrcode"
15
        "github.com/jackc/pgx/v4"
16
        "github.com/supabase/cli/pkg/pgxv5"
17
)
18

19
func ListRemoteMigrations(ctx context.Context, conn *pgx.Conn) ([]string, error) {
3✔
20
        // We query the version string only for backwards compatibility
3✔
21
        rows, _ := conn.Query(ctx, LIST_MIGRATION_VERSION)
3✔
22
        versions, err := pgxv5.CollectStrings(rows)
3✔
23
        if err != nil {
5✔
24
                var pgErr *pgconn.PgError
2✔
25
                if errors.As(err, &pgErr) && pgErr.Code == pgerrcode.UndefinedTable {
3✔
26
                        // If migration history table is undefined, the remote project has no migrations
1✔
27
                        return nil, nil
1✔
28
                }
1✔
29
        }
30
        return versions, err
2✔
31
}
32

33
func ListLocalMigrations(migrationsDir string, fsys fs.FS, filter ...func(string) bool) ([]string, error) {
3✔
34
        localMigrations, err := fs.ReadDir(fsys, migrationsDir)
3✔
35
        if err != nil && !errors.Is(err, os.ErrNotExist) {
4✔
36
                return nil, errors.Errorf("failed to read directory: %w", err)
1✔
37
        }
1✔
38
        if len(filter) == 0 {
4✔
39
                filter = append(filter, func(string) bool { return true })
4✔
40
        }
41
        var clean []string
2✔
42
        for i, migration := range localMigrations {
7✔
43
                filename := migration.Name()
5✔
44
                if i == 0 && shouldSkip(filename) {
6✔
45
                        fmt.Fprintf(os.Stderr, "Skipping migration %s... (replace \"init\" with a different file name to apply this migration)\n", filename)
1✔
46
                        continue
1✔
47
                }
48
                matches := migrateFilePattern.FindStringSubmatch(filename)
4✔
49
                if len(matches) == 0 {
6✔
50
                        fmt.Fprintf(os.Stderr, "Skipping migration %s... (file name must match pattern \"<timestamp>_name.sql\" or \"r_name.sql\")\n", filename)
2✔
51
                        continue
2✔
52
                }
53
                path := filepath.Join(migrationsDir, filename)
2✔
54
                for _, keep := range filter {
4✔
55
                        version := matches[1]
2✔
56
                        if version == "r" && len(matches) > 2 {
2✔
NEW
57
                                version += "_" + matches[2]
×
NEW
58
                        }
×
59
                        if keep(version) {
4✔
60
                                clean = append(clean, path)
2✔
61
                        }
2✔
62
                }
63
        }
64
        return clean, nil
2✔
65
}
66

67
var initSchemaPattern = regexp.MustCompile(`([0-9]{14})_init\.sql`)
68

69
func shouldSkip(name string) bool {
2✔
70
        // NOTE: To handle backward-compatibility. `<timestamp>_init.sql` as
2✔
71
        // the first migration (prev versions of the CLI) is deprecated.
2✔
72
        matches := initSchemaPattern.FindStringSubmatch(name)
2✔
73
        if len(matches) == 2 {
3✔
74
                if timestamp, err := strconv.ParseUint(matches[1], 10, 64); err == nil && timestamp < 20211209000000 {
2✔
75
                        return true
1✔
76
                }
1✔
77
        }
78
        return false
1✔
79
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc