Repository: supabase/cli
Pull request #1783 (2023-12-26 09:03:32)

feat: include migration history in db dump
## What kind of change does this PR introduce?

closes https://github.com/supabase/cli/issues/1671

## What is the new behavior?

Users typically want to restore the migration history table as well.

## Additional context

Add any other context or screenshots.


coveralls: ## Pull Request Test Coverage Report for [Build 7328291355](https://coveralls.io/builds/64759672)


* **14** of **16**   **(87.5%)**  changed or added relevant lines in **3** files are covered.
* **5** unchanged lines in **1** file lost coverage.
* Overall coverage decreased (**-0.04%**) to **58.35%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [internal/db/dump/dump.go](https://coveralls.io/builds/64759672/source?filename=internal%2Fdb%2Fdump%2Fdump.go#L96) | 0 | 1 | 0.0%
| [internal/db/lint/lint.go](https://coveralls.io/builds/64759672/source?filename=internal%2Fdb%2Flint%2Flint.go#L96) | 0 | 1 | 0.0%
<!-- | **Total:** | **14** | **16** | **87.5%** | -->

|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [internal/gen/keys/keys.go](https://coveralls.io/builds/64759672/source?filename=internal%2Fgen%2Fkeys%2Fkeys.go#L101) | 5 | 11.76% |
<!-- | **Total:** | **5** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/64759672/badge)](https://coveralls.io/builds/64759672) |
| :-- | --: |
| Change from base [Build 7325850169](https://coveralls.io/builds/64756771): |  -0.04% |
| Covered Lines: | 6003 |
| Relevant Lines: | 10288 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/internal/db/diff/migra.go b/internal/db/diff/migra.go
index caf4e96f..68e51e08 100644
--- a/internal/db/diff/migra.go
+++ b/internal/db/diff/migra.go
@@ -87,22 +87,20 @@ func loadSchema(ctx context.Context, config pgconn.Config, options ...func(*pgx.
 	return LoadUserSchemas(ctx, conn)
 }
 
-func LoadUserSchemas(ctx context.Context, conn *pgx.Conn, exclude ...string) ([]string, error) {
-	if len(exclude) == 0 {
-		// RLS policies in auth and storage schemas can be included with -s flag
-		exclude = append([]string{
-			"auth",
-			// "extensions",
-			"pgbouncer",
-			"realtime",
-			"_realtime",
-			"storage",
-			"_analytics",
-			// Exclude functions because Webhooks support is early alpha
-			"supabase_functions",
-			"supabase_migrations",
-		}, utils.SystemSchemas...)
-	}
+func LoadUserSchemas(ctx context.Context, conn *pgx.Conn) ([]string, error) {
+	// RLS policies in auth and storage schemas can be included with -s flag
+	exclude := append([]string{
+		"auth",
+		// "extensions",
+		"pgbouncer",
+		"realtime",
+		"_realtime",
+		"storage",
+		"_analytics",
+		// Exclude functions because Webhooks support is early alpha
+		"supabase_functions",
+		"supabase_migrations",
+	}, utils.SystemSchemas...)
 	return reset.ListSchemas(ctx, conn, exclude...)
 }
 
diff --git a/internal/db/dump/dump.go b/internal/db/dump/dump.go
index c365edca..3bcd3b87 100644
--- a/internal/db/dump/dump.go
+++ b/internal/db/dump/dump.go
@@ -93,7 +93,7 @@ func dumpData(ctx context.Context, config pgconn.Config, schema []string, useCop
 		// "storage",
 		"_analytics",
 		// "supabase_functions",
-		"supabase_migrations",
+		// "supabase_migrations",
 	}
 	env := []string{"EXCLUDED_SCHEMAS=" + strings.Join(excludedSchemas, "|")}
 	if len(schema) > 0 {
diff --git a/internal/db/lint/lint.go b/internal/db/lint/lint.go
index 22519ae5..dac3e837 100644
--- a/internal/db/lint/lint.go
+++ b/internal/db/lint/lint.go
@@ -13,7 +13,7 @@ import (
 	"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/reset"
 	"github.com/supabase/cli/internal/utils"
 )
 
@@ -93,7 +93,7 @@ func LintDatabase(ctx context.Context, conn *pgx.Conn, schema []string) ([]Resul
 		return nil, errors.Errorf("failed to begin transaction: %w", err)
 	}
 	if len(schema) == 0 {
-		schema, err = diff.LoadUserSchemas(ctx, conn, utils.InternalSchemas...)
+		schema, err = reset.ListSchemas(ctx, conn, utils.InternalSchemas...)
 		if err != nil {
 			return nil, err
 		}
diff --git a/internal/db/reset/reset.go b/internal/db/reset/reset.go
index d772abf1..0c59538f 100644
--- a/internal/db/reset/reset.go
+++ b/internal/db/reset/reset.go
@@ -274,7 +274,6 @@ func resetRemote(ctx context.Context, version string, config pgconn.Config, fsys
 	if err != nil {
 		return err
 	}
-	userSchemas = append(userSchemas, "supabase_migrations")
 	// Drop user defined objects
 	migration := repair.MigrationFile{}
 	for _, schema := range userSchemas {
diff --git a/internal/utils/misc.go b/internal/utils/misc.go
index 8546a1f3..3c963838 100644
--- a/internal/utils/misc.go
+++ b/internal/utils/misc.go
@@ -129,7 +129,6 @@ var (
 		"storage",
 		"_analytics",
 		"supabase_functions",
-		"supabase_migrations",
 	}, SystemSchemas...)
 	ReservedRoles = []string{
 		"anon",


Test patch:
diff --git a/internal/db/diff/migra_test.go b/internal/db/diff/migra_test.go
index 02cddb5f..f92cb63f 100644
--- a/internal/db/diff/migra_test.go
+++ b/internal/db/diff/migra_test.go
@@ -345,7 +345,7 @@ func TestUserSchema(t *testing.T) {
 	// Setup mock postgres
 	conn := pgtest.NewConn()
 	defer conn.Close(t)
-	conn.Query(strings.ReplaceAll(reset.LIST_SCHEMAS, "$1", "'{public}'")).
+	conn.Query(strings.ReplaceAll(reset.LIST_SCHEMAS, "$1", `'{auth,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","supabase\\_migrations","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}'`)).
 		Reply("SELECT 1", []interface{}{"test"})
 	// Connect to mock
 	ctx := context.Background()
@@ -353,7 +353,7 @@ func TestUserSchema(t *testing.T) {
 	require.NoError(t, err)
 	defer mock.Close(ctx)
 	// Run test
-	schemas, err := LoadUserSchemas(ctx, mock, "public")
+	schemas, err := LoadUserSchemas(ctx, mock)
 	// Check error
 	assert.NoError(t, err)
 	assert.ElementsMatch(t, []string{"test"}, schemas)
diff --git a/internal/db/reset/reset_test.go b/internal/db/reset/reset_test.go
index b65210ab..da0fd4d5 100644
--- a/internal/db/reset/reset_test.go
+++ b/internal/db/reset/reset_test.go
@@ -311,12 +311,10 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", "'{public,auth,extensions,pgbouncer,realtime,\"\\\\_realtime\",storage,\"\\\\_analytics\",\"supabase\\\\_functions\",\"supabase\\\\_migrations\",\"information\\\\_schema\",\"pg\\\\_%\",cron,graphql,\"graphql\\\\_public\",net,pgsodium,\"pgsodium\\\\_masks\",pgtle,repack,tiger,\"tiger\\\\_data\",\"timescaledb\\\\_%\",\"\\\\_timescaledb\\\\_%\",topology,vault}'")).
+		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", `'{public,auth,extensions,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}'`)).
 			Reply("SELECT 1", []interface{}{"private"}).
 			Query("DROP SCHEMA IF EXISTS private CASCADE").
 			Reply("DROP SCHEMA").
-			Query("DROP SCHEMA IF EXISTS supabase_migrations CASCADE").
-			Reply("DROP SCHEMA").
 			Query(dropObjects).
 			Reply("INSERT 0")
 		// Run test
@@ -340,7 +338,7 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", "'{public,auth,extensions,pgbouncer,realtime,\"\\\\_realtime\",storage,\"\\\\_analytics\",\"supabase\\\\_functions\",\"supabase\\\\_migrations\",\"information\\\\_schema\",\"pg\\\\_%\",cron,graphql,\"graphql\\\\_public\",net,pgsodium,\"pgsodium\\\\_masks\",pgtle,repack,tiger,\"tiger\\\\_data\",\"timescaledb\\\\_%\",\"\\\\_timescaledb\\\\_%\",topology,vault}'")).
+		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", `'{public,auth,extensions,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}'`)).
 			ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation information_schema")
 		// Run test
 		err := resetRemote(context.Background(), "", dbConfig, fsys, conn.Intercept)
@@ -354,11 +352,10 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", "'{public,auth,extensions,pgbouncer,realtime,\"\\\\_realtime\",storage,\"\\\\_analytics\",\"supabase\\\\_functions\",\"supabase\\\\_migrations\",\"information\\\\_schema\",\"pg\\\\_%\",cron,graphql,\"graphql\\\\_public\",net,pgsodium,\"pgsodium\\\\_masks\",pgtle,repack,tiger,\"tiger\\\\_data\",\"timescaledb\\\\_%\",\"\\\\_timescaledb\\\\_%\",topology,vault}'")).
+		conn.Query(strings.ReplaceAll(LIST_SCHEMAS, "$1", `'{public,auth,extensions,pgbouncer,realtime,"\\_realtime",storage,"\\_analytics","supabase\\_functions","information\\_schema","pg\\_%",cron,graphql,"graphql\\_public",net,pgsodium,"pgsodium\\_masks",pgtle,repack,tiger,"tiger\\_data","timescaledb\\_%","\\_timescaledb\\_%",topology,vault}'`)).
 			Reply("SELECT 0").
-			Query("DROP SCHEMA IF EXISTS supabase_migrations CASCADE").
-			ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation supabase_migrations").
-			Query(dropObjects)
+			Query(dropObjects).
+			ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation supabase_migrations")
 		// Run test
 		err := resetRemote(context.Background(), "", dbConfig, fsys, conn.Intercept)
 		// Check error