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

supabase / cli / 17567530040

09 Sep 2025 12:04AM UTC coverage: 54.772% (-0.04%) from 54.813%
17567530040

Pull #4132

github

web-flow
Merge a29a54951 into c605a3c39
Pull Request #4132: feat: on dump accept .pgpass file

0 of 4 new or added lines in 1 file covered. (0.0%)

7 existing lines in 2 files now uncovered.

6215 of 11347 relevant lines covered (54.77%)

6.07 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 views and grants.")
×
104
                        } else if !viper.GetBool("EXPERIMENTAL") {
×
105
                                differ = diff.DiffSchemaMigraBash
×
106
                        }
×
107
                        return diff.Run(cmd.Context(), schema, file, flags.DbConfig, differ, afero.NewOsFs())
×
108
                },
109
        }
110

111
        dataOnly     bool
112
        useCopy      bool
113
        roleOnly     bool
114
        keepComments bool
115
        excludeTable []string
116
        pgpassFile   string
117

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

149
        dryRun       bool
150
        includeAll   bool
151
        includeRoles bool
152
        includeSeed  bool
153

154
        dbPushCmd = &cobra.Command{
155
                Use:   "push",
156
                Short: "Push new migrations to the remote database",
157
                RunE: func(cmd *cobra.Command, args []string) error {
×
158
                        return push.Run(cmd.Context(), dryRun, includeAll, includeRoles, includeSeed, flags.DbConfig, afero.NewOsFs())
×
159
                },
×
160
        }
161

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

177
        dbRemoteCmd = &cobra.Command{
178
                Hidden: true,
179
                Use:    "remote",
180
                Short:  "Manage remote databases",
181
        }
182

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

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

202
        noSeed      bool
203
        lastVersion uint
204

205
        dbResetCmd = &cobra.Command{
206
                Use:   "reset",
207
                Short: "Resets the local database to current migrations",
208
                RunE: func(cmd *cobra.Command, args []string) error {
×
209
                        if noSeed {
×
210
                                utils.Config.Db.Seed.Enabled = false
×
211
                        }
×
212
                        return reset.Run(cmd.Context(), migrationVersion, lastVersion, flags.DbConfig, afero.NewOsFs())
×
213
                },
214
        }
215

216
        level = utils.EnumFlag{
217
                Allowed: lint.AllowedLevels,
218
                Value:   lint.AllowedLevels[0],
219
        }
220

221
        lintFailOn = utils.EnumFlag{
222
                Allowed: append([]string{"none"}, lint.AllowedLevels...),
223
                Value:   "none",
224
        }
225

226
        dbLintCmd = &cobra.Command{
227
                Use:   "lint",
228
                Short: "Checks local database for typing error",
229
                RunE: func(cmd *cobra.Command, args []string) error {
×
230
                        return lint.Run(cmd.Context(), schema, level.Value, lintFailOn.Value, flags.DbConfig, afero.NewOsFs())
×
231
                },
×
232
        }
233

234
        fromBackup string
235

236
        dbStartCmd = &cobra.Command{
237
                Use:   "start",
238
                Short: "Starts local Postgres database",
239
                RunE: func(cmd *cobra.Command, args []string) error {
×
240
                        return start.Run(cmd.Context(), fromBackup, afero.NewOsFs())
×
241
                },
×
242
        }
243

244
        dbTestCmd = &cobra.Command{
245
                Hidden: true,
246
                Use:    "test [path] ...",
247
                Short:  "Tests local database with pgTAP",
248
                RunE: func(cmd *cobra.Command, args []string) error {
×
249
                        return test.Run(cmd.Context(), args, flags.DbConfig, afero.NewOsFs())
×
250
                },
×
251
        }
252
)
253

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