diff --git a/cmd/db.go b/cmd/db.go index bcc7ac5e76..948f77bebe 100644 --- a/cmd/db.go +++ b/cmd/db.go @@ -18,8 +18,6 @@ import ( "github.com/supabase/cli/internal/db/lint" "github.com/supabase/cli/internal/db/pull" "github.com/supabase/cli/internal/db/push" - "github.com/supabase/cli/internal/db/remote/changes" - "github.com/supabase/cli/internal/db/remote/commit" "github.com/supabase/cli/internal/db/reset" "github.com/supabase/cli/internal/db/start" "github.com/supabase/cli/internal/db/test" @@ -175,7 +173,7 @@ var ( Short: "Show changes on the remote database", Long: "Show changes on the remote database since last migration.", RunE: func(cmd *cobra.Command, args []string) error { - return changes.Run(cmd.Context(), schema, flags.DbConfig, afero.NewOsFs()) + return diff.Run(cmd.Context(), schema, file, flags.DbConfig, diff.DiffSchemaMigra, afero.NewOsFs()) }, } @@ -184,7 +182,7 @@ var ( Use: "commit", Short: "Commit remote changes as a new migration", RunE: func(cmd *cobra.Command, args []string) error { - return commit.Run(cmd.Context(), schema, flags.DbConfig, afero.NewOsFs()) + return pull.Run(cmd.Context(), schema, flags.DbConfig, "remote_commit", afero.NewOsFs()) }, } @@ -304,10 +302,12 @@ func init() { dbCmd.AddCommand(dbPullCmd) // Build remote command remoteFlags := dbRemoteCmd.PersistentFlags() + remoteFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.") remoteFlags.String("db-url", "", "Connect using the specified Postgres URL (must be percent-encoded).") + remoteFlags.Bool("linked", true, "Connect to the linked project.") + dbRemoteCmd.MarkFlagsMutuallyExclusive("db-url", "linked") remoteFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.") cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", remoteFlags.Lookup("password"))) - remoteFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.") dbRemoteCmd.AddCommand(dbRemoteChangesCmd) dbRemoteCmd.AddCommand(dbRemoteCommitCmd) dbCmd.AddCommand(dbRemoteCmd) diff --git a/internal/db/remote/changes/changes.go b/internal/db/remote/changes/changes.go deleted file mode 100644 index 12c39288be..0000000000 --- a/internal/db/remote/changes/changes.go +++ /dev/null @@ -1,47 +0,0 @@ -package changes - -import ( - "context" - "io" - - "github.com/jackc/pgconn" - "github.com/spf13/afero" - "github.com/supabase/cli/internal/db/diff" - "github.com/supabase/cli/internal/utils" - "github.com/supabase/cli/pkg/migration" -) - -var output string - -func Run(ctx context.Context, schema []string, config pgconn.Config, fsys afero.Fs) error { - if err := utils.RunProgram(ctx, func(p utils.Program, ctx context.Context) error { - return run(p, ctx, schema, config, fsys) - }); err != nil { - return err - } - return diff.SaveDiff(output, "", fsys) -} - -func run(p utils.Program, ctx context.Context, schema []string, config pgconn.Config, fsys afero.Fs) (err error) { - // 1. Assert `supabase/migrations` and `schema_migrations` are in sync. - w := utils.StatusWriter{Program: p} - if len(schema) == 0 { - schema, err = loadSchema(ctx, config, w) - if err != nil { - return err - } - } - - // 2. Diff remote db (source) & shadow db (target) and print it. - output, err = diff.DiffDatabase(ctx, schema, config, w, fsys, diff.DiffSchemaMigra) - return err -} - -func loadSchema(ctx context.Context, config pgconn.Config, w io.Writer) ([]string, error) { - conn, err := utils.ConnectByConfigStream(ctx, config, w) - if err != nil { - return nil, err - } - defer conn.Close(context.Background()) - return migration.ListUserSchemas(ctx, conn) -} diff --git a/internal/db/remote/commit/commit.go b/internal/db/remote/commit/commit.go deleted file mode 100644 index 3e49346f6f..0000000000 --- a/internal/db/remote/commit/commit.go +++ /dev/null @@ -1,106 +0,0 @@ -package commit - -import ( - "context" - _ "embed" - "fmt" - "path/filepath" - - "github.com/go-errors/errors" - "github.com/jackc/pgconn" - "github.com/jackc/pgx/v4" - "github.com/spf13/afero" - "github.com/supabase/cli/internal/db/diff" - "github.com/supabase/cli/internal/db/dump" - "github.com/supabase/cli/internal/migration/list" - "github.com/supabase/cli/internal/migration/repair" - "github.com/supabase/cli/internal/utils" - "github.com/supabase/cli/pkg/migration" -) - -func Run(ctx context.Context, schema []string, config pgconn.Config, fsys afero.Fs) error { - if err := utils.RunProgram(ctx, func(p utils.Program, ctx context.Context) error { - return run(p, ctx, schema, config, fsys) - }); err != nil { - return err - } - fmt.Println("Finished " + utils.Aqua("supabase db remote commit") + ".") - return nil -} - -func run(p utils.Program, ctx context.Context, schema []string, config pgconn.Config, fsys afero.Fs) error { - // 1. Assert `supabase/migrations` and `schema_migrations` are in sync. - w := utils.StatusWriter{Program: p} - conn, err := utils.ConnectByConfigStream(ctx, config, w) - if err != nil { - return err - } - defer conn.Close(context.Background()) - if err := assertRemoteInSync(ctx, conn, fsys); err != nil { - return err - } - - // 2. Fetch remote schema changes - if len(schema) == 0 { - schema, err = migration.ListUserSchemas(ctx, conn) - if err != nil { - return err - } - } - timestamp := utils.GetCurrentTimestamp() - if err := fetchRemote(p, ctx, schema, timestamp, config, fsys); err != nil { - return err - } - - // 3. Insert a row to `schema_migrations` - return repair.UpdateMigrationTable(ctx, conn, []string{timestamp}, repair.Applied, false, fsys) -} - -func fetchRemote(p utils.Program, ctx context.Context, schema []string, timestamp string, config pgconn.Config, fsys afero.Fs) error { - path := filepath.Join(utils.MigrationsDir, timestamp+"_remote_commit.sql") - // Special case if this is the first migration - if migrations, err := migration.ListLocalMigrations(utils.MigrationsDir, afero.NewIOFS(fsys)); err != nil { - return err - } else if len(migrations) == 0 { - p.Send(utils.StatusMsg("Committing initial migration on remote database...")) - return dump.Run(ctx, path, config, nil, nil, false, false, false, false, false, fsys) - } - - w := utils.StatusWriter{Program: p} - // Diff remote db (source) & shadow db (target) and write it as a new migration. - output, err := diff.DiffDatabase(ctx, schema, config, w, fsys, diff.DiffSchemaMigra) - if err != nil { - return err - } - if len(output) == 0 { - return errors.New("No schema changes found") - } - return utils.WriteFile(path, []byte(output), fsys) -} - -func assertRemoteInSync(ctx context.Context, conn *pgx.Conn, fsys afero.Fs) error { - remoteMigrations, err := migration.ListRemoteMigrations(ctx, conn) - if err != nil { - return err - } - localMigrations, err := list.LoadLocalVersions(fsys) - if err != nil { - return err - } - - conflictErr := errors.New("The remote database's migration history is not in sync with the contents of " + utils.Bold(utils.MigrationsDir) + `. Resolve this by: -- Updating the project from version control to get the latest ` + utils.Bold(utils.MigrationsDir) + `, -- Pushing unapplied migrations with ` + utils.Aqua("supabase db push") + `, -- Or failing that, manually editing supabase_migrations.schema_migrations table with ` + utils.Aqua("supabase migration repair") + ".") - if len(remoteMigrations) != len(localMigrations) { - return conflictErr - } - - for i, remoteTimestamp := range remoteMigrations { - if localMigrations[i] != remoteTimestamp { - return conflictErr - } - } - - return nil -}