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

supabase / cli / 15489016285

06 Jun 2025 11:01AM UTC coverage: 55.018% (+0.2%) from 54.859%
15489016285

Pull #3673

github

web-flow
Merge dbb96ca7a into 865f304d5
Pull Request #3673: fix: move db dump to public pkg

15 of 43 new or added lines in 4 files covered. (34.88%)

5 existing lines in 1 file now uncovered.

5964 of 10840 relevant lines covered (55.02%)

6.11 hits per line

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

0.0
/cmd/db.go
1
package cmd
2

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

9
        "github.com/spf13/afero"
10
        "github.com/spf13/cobra"
11
        "github.com/spf13/viper"
12
        "github.com/supabase/cli/internal/db/branch/create"
13
        "github.com/supabase/cli/internal/db/branch/delete"
14
        "github.com/supabase/cli/internal/db/branch/list"
15
        "github.com/supabase/cli/internal/db/branch/switch_"
16
        "github.com/supabase/cli/internal/db/diff"
17
        "github.com/supabase/cli/internal/db/dump"
18
        "github.com/supabase/cli/internal/db/lint"
19
        "github.com/supabase/cli/internal/db/pull"
20
        "github.com/supabase/cli/internal/db/push"
21
        "github.com/supabase/cli/internal/db/reset"
22
        "github.com/supabase/cli/internal/db/start"
23
        "github.com/supabase/cli/internal/db/test"
24
        "github.com/supabase/cli/internal/utils"
25
        "github.com/supabase/cli/internal/utils/flags"
26
        "github.com/supabase/cli/pkg/migration"
27
)
28

29
var (
30
        dbCmd = &cobra.Command{
31
                GroupID: groupLocalDev,
32
                Use:     "db",
33
                Short:   "Manage Postgres databases",
34
                PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
×
35
                        ctx, _ := signal.NotifyContext(cmd.Context(), os.Interrupt)
×
36
                        cmd.SetContext(ctx)
×
37
                        return cmd.Root().PersistentPreRunE(cmd, args)
×
38
                },
×
39
        }
40

41
        dbBranchCmd = &cobra.Command{
42
                Hidden: true,
43
                Use:    "branch",
44
                Short:  "Manage local database branches",
45
                Long:   "Manage local database branches. Each branch is associated with a separate local database. Forking remote databases is NOT supported.",
46
        }
47

48
        dbBranchCreateCmd = &cobra.Command{
49
                Deprecated: "use \"branches create <name>\" instead.\n",
50
                Use:        "create <branch name>",
51
                Short:      "Create a branch",
52
                Args:       cobra.ExactArgs(1),
53
                RunE: func(cmd *cobra.Command, args []string) error {
×
54
                        return create.Run(args[0], afero.NewOsFs())
×
55
                },
×
56
        }
57

58
        dbBranchDeleteCmd = &cobra.Command{
59
                Deprecated: "use \"branches delete <branch-id>\" instead.\n",
60
                Use:        "delete <branch name>",
61
                Short:      "Delete a branch",
62
                Args:       cobra.ExactArgs(1),
63
                RunE: func(cmd *cobra.Command, args []string) error {
×
64
                        return delete.Run(args[0], afero.NewOsFs())
×
65
                },
×
66
        }
67

68
        dbBranchListCmd = &cobra.Command{
69
                Deprecated: "use \"branches list\" instead.\n",
70
                Use:        "list",
71
                Short:      "List branches",
72
                RunE: func(cmd *cobra.Command, args []string) error {
×
73
                        return list.Run(afero.NewOsFs(), os.Stdout)
×
74
                },
×
75
        }
76

77
        dbSwitchCmd = &cobra.Command{
78
                Deprecated: "use \"branches create <name>\" instead.\n",
79
                Use:        "switch <branch name>",
80
                Short:      "Switch the active branch",
81
                Args:       cobra.ExactArgs(1),
82
                RunE: func(cmd *cobra.Command, args []string) error {
×
83
                        return switch_.Run(cmd.Context(), args[0], afero.NewOsFs())
×
84
                },
×
85
        }
86

87
        useMigra    bool
88
        usePgAdmin  bool
89
        usePgSchema bool
90
        schema      []string
91
        file        string
92

93
        dbDiffCmd = &cobra.Command{
94
                Use:   "diff",
95
                Short: "Diffs the local database for schema changes",
96
                RunE: func(cmd *cobra.Command, args []string) error {
×
97
                        if usePgAdmin {
×
98
                                return diff.RunPgAdmin(cmd.Context(), schema, file, flags.DbConfig, afero.NewOsFs())
×
99
                        }
×
100
                        differ := diff.DiffSchemaMigra
×
101
                        if usePgSchema {
×
102
                                differ = diff.DiffPgSchema
×
103
                                fmt.Fprintln(os.Stderr, utils.Yellow("WARNING:"), "--use-pg-schema flag is experimental and may not include all entities, such as RLS policies, enums, and grants.")
×
104
                        }
×
105
                        return diff.Run(cmd.Context(), schema, file, flags.DbConfig, differ, afero.NewOsFs())
×
106
                },
107
        }
108

109
        dataOnly     bool
110
        useCopy      bool
111
        roleOnly     bool
112
        keepComments bool
113
        excludeTable []string
114

115
        dbDumpCmd = &cobra.Command{
116
                Use:   "dump",
117
                Short: "Dumps data or schemas from the remote database",
118
                PreRun: func(cmd *cobra.Command, args []string) {
×
119
                        if useCopy || len(excludeTable) > 0 {
×
120
                                cobra.CheckErr(cmd.MarkFlagRequired("data-only"))
×
121
                        }
×
122
                },
123
                RunE: func(cmd *cobra.Command, args []string) error {
×
NEW
124
                        opts := []migration.DumpOptionFunc{
×
NEW
125
                                migration.WithSchema(schema...),
×
NEW
126
                                migration.WithoutTable(excludeTable...),
×
NEW
127
                                migration.WithComments(keepComments),
×
NEW
128
                                migration.WithCopy(useCopy),
×
NEW
129
                        }
×
NEW
130
                        return dump.Run(cmd.Context(), file, flags.DbConfig, dataOnly, roleOnly, dryRun, afero.NewOsFs(), opts...)
×
131
                },
×
132
                PostRun: func(cmd *cobra.Command, args []string) {
×
133
                        if len(file) > 0 {
×
134
                                if absPath, err := filepath.Abs(file); err != nil {
×
135
                                        fmt.Fprintln(os.Stderr, "Dumped schema to "+utils.Bold(file)+".")
×
136
                                } else {
×
137
                                        fmt.Fprintln(os.Stderr, "Dumped schema to "+utils.Bold(absPath)+".")
×
138
                                }
×
139
                        }
140
                },
141
        }
142

143
        dryRun       bool
144
        includeAll   bool
145
        includeRoles bool
146
        includeSeed  bool
147

148
        dbPushCmd = &cobra.Command{
149
                Use:   "push",
150
                Short: "Push new migrations to the remote database",
151
                RunE: func(cmd *cobra.Command, args []string) error {
×
152
                        return push.Run(cmd.Context(), dryRun, includeAll, includeRoles, includeSeed, flags.DbConfig, afero.NewOsFs())
×
153
                },
×
154
        }
155

156
        dbPullCmd = &cobra.Command{
157
                Use:   "pull [migration name]",
158
                Short: "Pull schema from the remote database",
159
                RunE: func(cmd *cobra.Command, args []string) error {
×
160
                        name := "remote_schema"
×
161
                        if len(args) > 0 {
×
162
                                name = args[0]
×
163
                        }
×
164
                        return pull.Run(cmd.Context(), schema, flags.DbConfig, name, afero.NewOsFs())
×
165
                },
166
                PostRun: func(cmd *cobra.Command, args []string) {
×
167
                        fmt.Println("Finished " + utils.Aqua("supabase db pull") + ".")
×
168
                },
×
169
        }
170

171
        dbRemoteCmd = &cobra.Command{
172
                Hidden: true,
173
                Use:    "remote",
174
                Short:  "Manage remote databases",
175
        }
176

177
        dbRemoteChangesCmd = &cobra.Command{
178
                Deprecated: "use \"db diff --use-migra --linked\" instead.\n",
179
                Use:        "changes",
180
                Short:      "Show changes on the remote database",
181
                Long:       "Show changes on the remote database since last migration.",
182
                RunE: func(cmd *cobra.Command, args []string) error {
×
183
                        return diff.Run(cmd.Context(), schema, file, flags.DbConfig, diff.DiffSchemaMigra, afero.NewOsFs())
×
184
                },
×
185
        }
186

187
        dbRemoteCommitCmd = &cobra.Command{
188
                Deprecated: "use \"db pull\" instead.\n",
189
                Use:        "commit",
190
                Short:      "Commit remote changes as a new migration",
191
                RunE: func(cmd *cobra.Command, args []string) error {
×
192
                        return pull.Run(cmd.Context(), schema, flags.DbConfig, "remote_commit", afero.NewOsFs())
×
193
                },
×
194
        }
195

196
        noSeed bool
197

198
        dbResetCmd = &cobra.Command{
199
                Use:   "reset",
200
                Short: "Resets the local database to current migrations",
201
                RunE: func(cmd *cobra.Command, args []string) error {
×
202
                        if noSeed {
×
203
                                utils.Config.Db.Seed.Enabled = false
×
204
                        }
×
205
                        return reset.Run(cmd.Context(), migrationVersion, nLastVersion, flags.DbConfig, afero.NewOsFs())
×
206
                },
207
        }
208

209
        level = utils.EnumFlag{
210
                Allowed: lint.AllowedLevels,
211
                Value:   lint.AllowedLevels[0],
212
        }
213

214
        lintFailOn = utils.EnumFlag{
215
                Allowed: append([]string{"none"}, lint.AllowedLevels...),
216
                Value:   "none",
217
        }
218

219
        dbLintCmd = &cobra.Command{
220
                Use:   "lint",
221
                Short: "Checks local database for typing error",
222
                RunE: func(cmd *cobra.Command, args []string) error {
×
223
                        return lint.Run(cmd.Context(), schema, level.Value, lintFailOn.Value, flags.DbConfig, afero.NewOsFs())
×
224
                },
×
225
        }
226

227
        fromBackup string
228

229
        dbStartCmd = &cobra.Command{
230
                Use:   "start",
231
                Short: "Starts local Postgres database",
232
                RunE: func(cmd *cobra.Command, args []string) error {
×
233
                        return start.Run(cmd.Context(), fromBackup, afero.NewOsFs())
×
234
                },
×
235
        }
236

237
        dbTestCmd = &cobra.Command{
238
                Hidden: true,
239
                Use:    "test [path] ...",
240
                Short:  "Tests local database with pgTAP",
241
                RunE: func(cmd *cobra.Command, args []string) error {
×
242
                        return test.Run(cmd.Context(), args, flags.DbConfig, afero.NewOsFs())
×
243
                },
×
244
        }
245
)
246

247
func init() {
×
248
        // Build branch command
×
249
        dbBranchCmd.AddCommand(dbBranchCreateCmd)
×
250
        dbBranchCmd.AddCommand(dbBranchDeleteCmd)
×
251
        dbBranchCmd.AddCommand(dbBranchListCmd)
×
252
        dbBranchCmd.AddCommand(dbSwitchCmd)
×
253
        dbCmd.AddCommand(dbBranchCmd)
×
254
        // Build diff command
×
255
        diffFlags := dbDiffCmd.Flags()
×
256
        diffFlags.BoolVar(&useMigra, "use-migra", true, "Use migra to generate schema diff.")
×
257
        diffFlags.BoolVar(&usePgAdmin, "use-pgadmin", false, "Use pgAdmin to generate schema diff.")
×
258
        diffFlags.BoolVar(&usePgSchema, "use-pg-schema", false, "Use pg-schema-diff to generate schema diff.")
×
259
        dbDiffCmd.MarkFlagsMutuallyExclusive("use-migra", "use-pgadmin")
×
260
        diffFlags.String("db-url", "", "Diffs against the database specified by the connection string (must be percent-encoded).")
×
261
        diffFlags.Bool("linked", false, "Diffs local migration files against the linked project.")
×
262
        diffFlags.Bool("local", true, "Diffs local migration files against the local database.")
×
263
        dbDiffCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
264
        diffFlags.StringVarP(&file, "file", "f", "", "Saves schema diff to a new migration file.")
×
265
        diffFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
266
        dbCmd.AddCommand(dbDiffCmd)
×
267
        // Build dump command
×
268
        dumpFlags := dbDumpCmd.Flags()
×
269
        dumpFlags.BoolVar(&dryRun, "dry-run", false, "Prints the pg_dump script that would be executed.")
×
270
        dumpFlags.BoolVar(&dataOnly, "data-only", false, "Dumps only data records.")
×
271
        dumpFlags.BoolVar(&useCopy, "use-copy", false, "Uses copy statements in place of inserts.")
×
272
        dumpFlags.StringSliceVarP(&excludeTable, "exclude", "x", []string{}, "List of schema.tables to exclude from data-only dump.")
×
273
        dumpFlags.BoolVar(&roleOnly, "role-only", false, "Dumps only cluster roles.")
×
274
        dbDumpCmd.MarkFlagsMutuallyExclusive("role-only", "data-only")
×
275
        dumpFlags.BoolVar(&keepComments, "keep-comments", false, "Keeps commented lines from pg_dump output.")
×
276
        dbDumpCmd.MarkFlagsMutuallyExclusive("keep-comments", "data-only")
×
277
        dumpFlags.StringVarP(&file, "file", "f", "", "File path to save the dumped contents.")
×
278
        dumpFlags.String("db-url", "", "Dumps from the database specified by the connection string (must be percent-encoded).")
×
279
        dumpFlags.Bool("linked", true, "Dumps from the linked project.")
×
280
        dumpFlags.Bool("local", false, "Dumps from the local database.")
×
281
        dbDumpCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
282
        dumpFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.")
×
283
        cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", dumpFlags.Lookup("password")))
×
284
        dumpFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
285
        dbDumpCmd.MarkFlagsMutuallyExclusive("schema", "role-only")
×
286
        dbCmd.AddCommand(dbDumpCmd)
×
287
        // Build push command
×
288
        pushFlags := dbPushCmd.Flags()
×
289
        pushFlags.BoolVar(&includeAll, "include-all", false, "Include all migrations not found on remote history table.")
×
290
        pushFlags.BoolVar(&includeRoles, "include-roles", false, "Include custom roles from "+utils.CustomRolesPath+".")
×
291
        pushFlags.BoolVar(&includeSeed, "include-seed", false, "Include seed data from your config.")
×
292
        pushFlags.BoolVar(&dryRun, "dry-run", false, "Print the migrations that would be applied, but don't actually apply them.")
×
293
        pushFlags.String("db-url", "", "Pushes to the database specified by the connection string (must be percent-encoded).")
×
294
        pushFlags.Bool("linked", true, "Pushes to the linked project.")
×
295
        pushFlags.Bool("local", false, "Pushes to the local database.")
×
296
        dbPushCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
297
        pushFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.")
×
298
        cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", pushFlags.Lookup("password")))
×
299
        dbCmd.AddCommand(dbPushCmd)
×
300
        // Build pull command
×
301
        pullFlags := dbPullCmd.Flags()
×
302
        pullFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
303
        pullFlags.String("db-url", "", "Pulls from the database specified by the connection string (must be percent-encoded).")
×
304
        pullFlags.Bool("linked", true, "Pulls from the linked project.")
×
305
        pullFlags.Bool("local", false, "Pulls from the local database.")
×
306
        dbPullCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
307
        pullFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.")
×
308
        cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", pullFlags.Lookup("password")))
×
309
        dbCmd.AddCommand(dbPullCmd)
×
310
        // Build remote command
×
311
        remoteFlags := dbRemoteCmd.PersistentFlags()
×
312
        remoteFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
313
        remoteFlags.String("db-url", "", "Connect using the specified Postgres URL (must be percent-encoded).")
×
314
        remoteFlags.Bool("linked", true, "Connect to the linked project.")
×
315
        dbRemoteCmd.MarkFlagsMutuallyExclusive("db-url", "linked")
×
316
        remoteFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.")
×
317
        cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", remoteFlags.Lookup("password")))
×
318
        dbRemoteCmd.AddCommand(dbRemoteChangesCmd)
×
319
        dbRemoteCmd.AddCommand(dbRemoteCommitCmd)
×
320
        dbCmd.AddCommand(dbRemoteCmd)
×
321
        // Build reset command
×
322
        resetFlags := dbResetCmd.Flags()
×
323
        resetFlags.String("db-url", "", "Resets the database specified by the connection string (must be percent-encoded).")
×
324
        resetFlags.Bool("linked", false, "Resets the linked project with local migrations.")
×
325
        resetFlags.Bool("local", true, "Resets the local database with local migrations.")
×
326
        resetFlags.BoolVar(&noSeed, "no-seed", false, "Skip running the seed script after reset.")
×
327
        dbResetCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
328
        resetFlags.StringVar(&migrationVersion, "version", "", "Reset up to the specified version.")
×
329
        resetFlags.UintVar(&nLastVersion, "last", 0, "Reset up to the last n migration versions.")
×
330
        dbResetCmd.MarkFlagsMutuallyExclusive("version", "last")
×
331
        dbCmd.AddCommand(dbResetCmd)
×
332
        // Build lint command
×
333
        lintFlags := dbLintCmd.Flags()
×
334
        lintFlags.String("db-url", "", "Lints the database specified by the connection string (must be percent-encoded).")
×
335
        lintFlags.Bool("linked", false, "Lints the linked project for schema errors.")
×
336
        lintFlags.Bool("local", true, "Lints the local database for schema errors.")
×
337
        dbLintCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
338
        lintFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
339
        lintFlags.Var(&level, "level", "Error level to emit.")
×
340
        lintFlags.Var(&lintFailOn, "fail-on", "Error level to exit with non-zero status.")
×
341
        dbCmd.AddCommand(dbLintCmd)
×
342
        // Build start command
×
343
        startFlags := dbStartCmd.Flags()
×
344
        startFlags.StringVar(&fromBackup, "from-backup", "", "Path to a logical backup file.")
×
345
        dbCmd.AddCommand(dbStartCmd)
×
346
        // Build test command
×
347
        dbCmd.AddCommand(dbTestCmd)
×
348
        testFlags := dbTestCmd.Flags()
×
349
        testFlags.String("db-url", "", "Tests the database specified by the connection string (must be percent-encoded).")
×
350
        testFlags.Bool("linked", false, "Runs pgTAP tests on the linked project.")
×
351
        testFlags.Bool("local", true, "Runs pgTAP tests on the local database.")
×
352
        dbTestCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
353
        rootCmd.AddCommand(dbCmd)
×
354
}
×
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