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

supabase / cli / 23253461919

18 Mar 2026 03:45PM UTC coverage: 63.53% (+1.6%) from 61.9%
23253461919

Pull #4966

github

web-flow
Merge 7e5d417b9 into bce705147
Pull Request #4966: feat: add pg delta declarative sync command

517 of 1437 new or added lines in 17 files covered. (35.98%)

8 existing lines in 4 files now uncovered.

9156 of 14412 relevant lines covered (63.53%)

6.89 hits per line

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

67.86
/internal/db/declarative/debug.go
1
package declarative
2

3
import (
4
        "fmt"
5
        "os"
6
        "path/filepath"
7
        "time"
8

9
        "github.com/spf13/afero"
10
        "github.com/supabase/cli/internal/utils"
11
        "github.com/supabase/cli/pkg/migration"
12
)
13

14
const (
15
        debugDirPrefix = "debug"
16
        debugLayout    = "20060102-150405"
17
)
18

19
// DebugBundle collects diagnostic artifacts when a declarative operation fails.
20
type DebugBundle struct {
21
        ID           string   // timestamp-based unique ID (e.g. "20240414-044403")
22
        SourceRef    string   // path to source catalog
23
        TargetRef    string   // path to target catalog
24
        MigrationSQL string   // generated migration (if available)
25
        Error        error    // the error that occurred
26
        Migrations   []string // list of local migration files
27
}
28

29
// SaveDebugBundle writes diagnostic artifacts to .temp/pgdelta/debug/<ID>/ and
30
// returns the directory path.
31
func SaveDebugBundle(bundle DebugBundle, fsys afero.Fs) (string, error) {
5✔
32
        if len(bundle.ID) == 0 {
6✔
33
                bundle.ID = time.Now().UTC().Format(debugLayout)
1✔
34
        }
1✔
35
        debugDir := filepath.Join(utils.TempDir, pgDeltaTempDir, debugDirPrefix, bundle.ID)
5✔
36
        if err := utils.MkdirIfNotExistFS(fsys, debugDir); err != nil {
6✔
37
                return "", fmt.Errorf("failed to create debug directory: %w", err)
1✔
38
        }
1✔
39

40
        // Copy source catalog if available
41
        if len(bundle.SourceRef) > 0 {
5✔
42
                if data, err := afero.ReadFile(fsys, bundle.SourceRef); err == nil {
2✔
43
                        _ = utils.WriteFile(filepath.Join(debugDir, "source-catalog.json"), data, fsys)
1✔
44
                }
1✔
45
        }
46

47
        // Copy target catalog if available
48
        if len(bundle.TargetRef) > 0 {
5✔
49
                if data, err := afero.ReadFile(fsys, bundle.TargetRef); err == nil {
2✔
50
                        _ = utils.WriteFile(filepath.Join(debugDir, "target-catalog.json"), data, fsys)
1✔
51
                }
1✔
52
        }
53

54
        // Save generated migration if available
55
        if len(bundle.MigrationSQL) > 0 {
6✔
56
                _ = utils.WriteFile(filepath.Join(debugDir, "generated-migration.sql"), []byte(bundle.MigrationSQL), fsys)
2✔
57
        }
2✔
58

59
        // Save error details
60
        if bundle.Error != nil {
8✔
61
                _ = utils.WriteFile(filepath.Join(debugDir, "error.txt"), []byte(bundle.Error.Error()), fsys)
4✔
62
        }
4✔
63

64
        // Copy migration files
65
        if len(bundle.Migrations) > 0 {
6✔
66
                migrationsDir := filepath.Join(debugDir, "migrations")
2✔
67
                if err := utils.MkdirIfNotExistFS(fsys, migrationsDir); err == nil {
4✔
68
                        for _, name := range bundle.Migrations {
5✔
69
                                src := filepath.Join(utils.MigrationsDir, name)
3✔
70
                                if data, err := afero.ReadFile(fsys, src); err == nil {
6✔
71
                                        _ = utils.WriteFile(filepath.Join(migrationsDir, name), data, fsys)
3✔
72
                                }
3✔
73
                        }
74
                }
75
        }
76

77
        return debugDir, nil
4✔
78
}
79

80
// PrintDebugBundleMessage prints instructions for reporting an issue after
81
// saving a debug bundle.
NEW
82
func PrintDebugBundleMessage(debugDir string) {
×
NEW
83
        fmt.Fprintln(os.Stderr)
×
NEW
84
        if len(debugDir) > 0 {
×
NEW
85
                fmt.Fprintln(os.Stderr, "Debug information saved to "+utils.Bold(debugDir))
×
NEW
86
                fmt.Fprintln(os.Stderr)
×
NEW
87
        }
×
NEW
88
        fmt.Fprintln(os.Stderr, "To report this issue, you can:")
×
NEW
89
        fmt.Fprintln(os.Stderr, "  1. Open an issue at https://github.com/supabase/pg-toolbelt/issues")
×
NEW
90
        fmt.Fprintln(os.Stderr, "     Attach the files from the debug folder above.")
×
NEW
91
        fmt.Fprintln(os.Stderr, "  2. Open a support ticket at https://supabase.com/dashboard/support")
×
NEW
92
        fmt.Fprintln(os.Stderr, "     (only visible to Supabase employees)")
×
NEW
93
        fmt.Fprintln(os.Stderr)
×
NEW
94
        fmt.Fprintln(os.Stderr, utils.Yellow("WARNING: The debug folder may contain sensitive information about your"))
×
NEW
95
        fmt.Fprintln(os.Stderr, utils.Yellow("database schema, including table structures, function definitions, and role"))
×
NEW
96
        fmt.Fprintln(os.Stderr, utils.Yellow("configurations. Review the contents carefully before sharing publicly."))
×
NEW
97
        fmt.Fprintln(os.Stderr, utils.Yellow("If unsure, prefer opening a support ticket (option 2) instead."))
×
98
}
99

100
// CollectMigrationsList returns a list of local migration filenames for
101
// inclusion in a debug bundle.
102
func CollectMigrationsList(fsys afero.Fs) []string {
4✔
103
        migrations, err := migration.ListLocalMigrations(utils.MigrationsDir, afero.NewIOFS(fsys))
4✔
104
        if err != nil {
4✔
NEW
105
                return nil
×
NEW
106
        }
×
107
        // Strip directory prefix to return just filenames
108
        for i, m := range migrations {
7✔
109
                migrations[i] = filepath.Base(m)
3✔
110
        }
3✔
111
        return migrations
4✔
112
}
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

© 2026 Coveralls, Inc