Repository: supabase/cli
Pull request #2200 (2024-04-23 02:12:21)

Prod deploy


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2ef1609b..38837411 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -41,7 +41,7 @@ jobs:
           # Linter requires no cache
           cache: false
 
-      - uses: golangci/golangci-lint-action@v4
+      - uses: golangci/golangci-lint-action@v5
         with:
           args: --timeout 3m --verbose
 
diff --git a/cmd/bootstrap.go b/cmd/bootstrap.go
index 4863077e..29ab2eef 100644
--- a/cmd/bootstrap.go
+++ b/cmd/bootstrap.go
@@ -30,10 +30,7 @@ var (
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if !viper.IsSet("WORKDIR") {
 				title := fmt.Sprintf("Enter a directory to bootstrap your project (or leave blank to use %s): ", utils.Bold(utils.CurrentDirAbs))
-				workdir, err := utils.NewConsole().PromptText(title)
-				if err != nil {
-					return err
-				}
+				workdir := utils.NewConsole().PromptText(title)
 				viper.Set("WORKDIR", workdir)
 			}
 			ctx, _ := signal.NotifyContext(cmd.Context(), os.Interrupt)
diff --git a/cmd/branches.go b/cmd/branches.go
index a4cd651d..4550fc09 100644
--- a/cmd/branches.go
+++ b/cmd/branches.go
@@ -177,11 +177,12 @@ func promptBranchId(ctx context.Context, ref string) error {
 		if len(gitBranch) > 0 {
 			title = fmt.Sprintf("%-2s (or leave blank to use %s): ", title, utils.Aqua(gitBranch))
 		}
-		if name, err := console.PromptText(title); err != nil {
-			return err
-		} else if len(name) > 0 {
+		if name := console.PromptText(title); len(name) > 0 {
 			gitBranch = name
 		}
+		if len(gitBranch) == 0 {
+			return errors.New("git branch cannot be empty")
+		}
 		for _, branch := range *resp.JSON200 {
 			if branch.Name == gitBranch {
 				branchId = branch.Id
diff --git a/go.mod b/go.mod
index e806ef20..bfb45205 100644
--- a/go.mod
+++ b/go.mod
@@ -13,8 +13,8 @@ require (
 	github.com/charmbracelet/lipgloss v0.10.0
 	github.com/containers/common v0.58.2
 	github.com/deepmap/oapi-codegen v1.16.2
-	github.com/docker/cli v26.0.2+incompatible
-	github.com/docker/docker v26.0.2+incompatible
+	github.com/docker/cli v26.1.0+incompatible
+	github.com/docker/docker v26.1.0+incompatible
 	github.com/docker/go-connections v0.5.0
 	github.com/docker/go-units v0.5.0
 	github.com/getsentry/sentry-go v0.27.0
@@ -174,6 +174,7 @@ require (
 	github.com/gostaticanalysis/comment v1.4.2 // indirect
 	github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
 	github.com/gostaticanalysis/nilerr v0.1.1 // indirect
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
 	github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
 	github.com/hashicorp/go-version v1.6.0 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
@@ -310,11 +311,16 @@ require (
 	go-simpler.org/musttag v0.9.0 // indirect
 	go-simpler.org/sloglint v0.5.0 // indirect
 	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
-	go.opentelemetry.io/otel v1.24.0 // indirect
+	go.opentelemetry.io/otel v1.25.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.25.0 // indirect
 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
-	go.opentelemetry.io/otel/metric v1.24.0 // indirect
-	go.opentelemetry.io/otel/sdk v1.24.0 // indirect
-	go.opentelemetry.io/otel/trace v1.24.0 // indirect
+	go.opentelemetry.io/otel/metric v1.25.0 // indirect
+	go.opentelemetry.io/otel/sdk v1.25.0 // indirect
+	go.opentelemetry.io/otel/sdk/metric v1.25.0 // indirect
+	go.opentelemetry.io/otel/trace v1.25.0 // indirect
+	go.opentelemetry.io/proto/otlp v1.1.0 // indirect
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/automaxprocs v1.5.3 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
@@ -328,6 +334,8 @@ require (
 	golang.org/x/sys v0.19.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/tools v0.19.0 // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
 	google.golang.org/protobuf v1.33.0 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
diff --git a/go.sum b/go.sum
index 40f1c6bd..7bc0b265 100644
--- a/go.sum
+++ b/go.sum
@@ -233,13 +233,13 @@ github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E
 github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
 github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk=
 github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE=
-github.com/docker/cli v26.0.2+incompatible h1:4C4U8ZqrlNDe/R1U1zFFX+YsCFiVUicJqo4WVdInJas=
-github.com/docker/cli v26.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/cli v26.1.0+incompatible h1:+nwRy8Ocd8cYNQ60mozDDICICD8aoFGtlPXifX/UQ3Y=
+github.com/docker/cli v26.1.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
 github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v26.0.2+incompatible h1:yGVmKUFGgcxA6PXWAokO0sQL22BrQ67cgVjko8tGdXE=
-github.com/docker/docker v26.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v26.1.0+incompatible h1:W1G9MPNbskA6VZWL7b3ZljTh0pXI68FpINx0GKaOdaM=
+github.com/docker/docker v26.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo=
 github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
 github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
@@ -1031,18 +1031,24 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
-go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
-go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA=
+go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k=
+go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg=
+go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 h1:hDKnobznDpcdTlNzO0S/owRB8tyVr1OoeZZhDoqY+Cs=
+go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0/go.mod h1:kUDQaUs1h8iTIHbQTk+iJRiUvSfJYMMKTtMCaiVu7B0=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0 h1:dT33yIHtmsqpixFsSQPwNeY5drM9wTcoL8h0FWF4oGM=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0/go.mod h1:h95q0LBGh7hlAC08X2DhSeyIG02YQ0UyioTCVAqRPmc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.25.0 h1:vOL89uRfOCCNIjkisd0r7SEdJF3ZJFyCNY34fdZs8eU=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.25.0/go.mod h1:8GlBGcDk8KKi7n+2S4BT/CPZQYH3erLu0/k64r1MYgo=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs=
 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM=
-go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
-go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
-go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
-go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
-go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
-go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
+go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA=
+go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s=
+go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo=
+go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw=
+go.opentelemetry.io/otel/sdk/metric v1.25.0 h1:7CiHOy08LbrxMAp4vWpbiPcklunUshVpAvGBrdDRlGw=
+go.opentelemetry.io/otel/sdk/metric v1.25.0/go.mod h1:LzwoKptdbBBdYfvtGCzGwk6GWMA3aUzBOwtQpR6Nz7o=
+go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM=
+go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I=
 go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
 go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -1053,8 +1059,8 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
 go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
-go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
-go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@@ -1446,10 +1452,11 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
+google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
 google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
 google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
 google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
diff --git a/internal/db/diff/diff.go b/internal/db/diff/diff.go
index 9f90fe3c..e60c8883 100644
--- a/internal/db/diff/diff.go
+++ b/internal/db/diff/diff.go
@@ -83,24 +83,8 @@ func loadSchema(ctx context.Context, config pgconn.Config, options ...func(*pgx.
 		return nil, err
 	}
 	defer conn.Close(context.Background())
-	return LoadUserSchemas(ctx, conn)
-}
-
-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...)
+	return reset.LoadUserSchemas(ctx, conn)
 }
 
 func CreateShadowDatabase(ctx context.Context) (string, error) {
diff --git a/internal/db/dump/templates/dump_schema.sh b/internal/db/dump/templates/dump_schema.sh
index 4703fc11..07e267ac 100755
--- a/internal/db/dump/templates/dump_schema.sh
+++ b/internal/db/dump/templates/dump_schema.sh
@@ -18,7 +18,7 @@ export PGDATABASE="$PGDATABASE"
 #   - do not include ACL changes on internal schemas
 #   - do not include RLS policies on cron extension schema
 #   - do not include event triggers
-#   - do not include creating publication "supabase_realtime"
+#   - do not create publication "supabase_realtime"
 pg_dump \
     --schema-only \
     --quote-all-identifier \
diff --git a/internal/db/lint/lint.go b/internal/db/lint/lint.go
index dac3e837..b65b44e4 100644
--- a/internal/db/lint/lint.go
+++ b/internal/db/lint/lint.go
@@ -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 = reset.ListSchemas(ctx, conn, utils.InternalSchemas...)
+		schema, err = reset.LoadUserSchemas(ctx, conn)
 		if err != nil {
 			return nil, err
 		}
diff --git a/internal/db/pull/pull.go b/internal/db/pull/pull.go
index a73bb7a6..c7b3b755 100644
--- a/internal/db/pull/pull.go
+++ b/internal/db/pull/pull.go
@@ -14,6 +14,7 @@ import (
 	"github.com/spf13/afero"
 	"github.com/supabase/cli/internal/db/diff"
 	"github.com/supabase/cli/internal/db/dump"
+	"github.com/supabase/cli/internal/db/reset"
 	"github.com/supabase/cli/internal/migration/list"
 	"github.com/supabase/cli/internal/migration/new"
 	"github.com/supabase/cli/internal/migration/repair"
@@ -78,7 +79,7 @@ func run(p utils.Program, ctx context.Context, schema []string, path string, con
 	defaultSchema := len(schema) == 0
 	if defaultSchema {
 		var err error
-		schema, err = diff.LoadUserSchemas(ctx, conn)
+		schema, err = reset.LoadUserSchemas(ctx, conn)
 		if err != nil {
 			return err
 		}
diff --git a/internal/db/remote/changes/changes.go b/internal/db/remote/changes/changes.go
index b6d77f37..2bdd3abe 100644
--- a/internal/db/remote/changes/changes.go
+++ b/internal/db/remote/changes/changes.go
@@ -7,6 +7,7 @@ import (
 	"github.com/jackc/pgconn"
 	"github.com/spf13/afero"
 	"github.com/supabase/cli/internal/db/diff"
+	"github.com/supabase/cli/internal/db/reset"
 	"github.com/supabase/cli/internal/utils"
 )
 
@@ -53,5 +54,5 @@ func loadSchema(ctx context.Context, config pgconn.Config, w io.Writer) ([]strin
 		return nil, err
 	}
 	defer conn.Close(context.Background())
-	return diff.LoadUserSchemas(ctx, conn)
+	return reset.LoadUserSchemas(ctx, conn)
 }
diff --git a/internal/db/remote/commit/commit.go b/internal/db/remote/commit/commit.go
index c58a7a61..3669c869 100644
--- a/internal/db/remote/commit/commit.go
+++ b/internal/db/remote/commit/commit.go
@@ -12,6 +12,7 @@ import (
 	"github.com/spf13/afero"
 	"github.com/supabase/cli/internal/db/diff"
 	"github.com/supabase/cli/internal/db/dump"
+	"github.com/supabase/cli/internal/db/reset"
 	"github.com/supabase/cli/internal/migration/list"
 	"github.com/supabase/cli/internal/migration/repair"
 	"github.com/supabase/cli/internal/utils"
@@ -52,7 +53,7 @@ func run(p utils.Program, ctx context.Context, schema []string, config pgconn.Co
 
 	// 2. Fetch remote schema changes
 	if len(schema) == 0 {
-		schema, err = diff.LoadUserSchemas(ctx, conn)
+		schema, err = reset.LoadUserSchemas(ctx, conn)
 		if err != nil {
 			return err
 		}
diff --git a/internal/db/reset/reset.go b/internal/db/reset/reset.go
index a6311dc3..0dffec00 100644
--- a/internal/db/reset/reset.go
+++ b/internal/db/reset/reset.go
@@ -28,16 +28,13 @@ import (
 	"github.com/supabase/cli/internal/utils/pgxv5"
 )
 
-const (
-	SET_POSTGRES_ROLE = "SET ROLE postgres;"
-	LIST_SCHEMAS      = "SELECT schema_name FROM information_schema.schemata WHERE NOT schema_name LIKE ANY($1) ORDER BY schema_name"
-)
-
 var (
 	ErrUnhealthy   = errors.New("service not healthy")
 	serviceTimeout = 30 * time.Second
 	//go:embed templates/drop.sql
 	dropObjects string
+	//go:embed templates/list.sql
+	ListSchemas string
 )
 
 func Run(ctx context.Context, version string, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
@@ -264,23 +261,24 @@ func resetRemote(ctx context.Context, version string, config pgconn.Config, fsys
 		return err
 	}
 	defer conn.Close(context.Background())
-	// List user defined schemas
-	excludes := []string{"public"}
-	for _, schema := range utils.InternalSchemas {
-		if schema != "supabase_migrations" {
-			excludes = append(excludes, schema)
-		}
-	}
-	userSchemas, err := ListSchemas(ctx, conn, excludes...)
+	// Only drop objects in extensions and public schema
+	excludes := append([]string{
+		"extensions",
+		"public",
+	}, utils.ManagedSchemas...)
+	userSchemas, err := LoadUserSchemas(ctx, conn, excludes...)
 	if err != nil {
 		return err
 	}
-	// Drop user defined objects
+	// Drop all user defined schemas
 	migration := repair.MigrationFile{}
 	for _, schema := range userSchemas {
 		sql := fmt.Sprintf("DROP SCHEMA IF EXISTS %s CASCADE", schema)
 		migration.Lines = append(migration.Lines, sql)
 	}
+	// If an extension uses a schema it doesn't create, dropping the schema will cascade to also
+	// drop the extension. But if an extension creates its own schema, dropping the schema will
+	// throw an error. Hence, we drop the extension instead so it cascades to its own schema.
 	migration.Lines = append(migration.Lines, dropObjects)
 	if err := migration.ExecBatch(ctx, conn); err != nil {
 		return err
@@ -288,15 +286,16 @@ func resetRemote(ctx context.Context, version string, config pgconn.Config, fsys
 	return apply.MigrateAndSeed(ctx, version, conn, fsys)
 }
 
-func ListSchemas(ctx context.Context, conn *pgx.Conn, exclude ...string) ([]string, error) {
-	exclude = LikeEscapeSchema(exclude)
+func LoadUserSchemas(ctx context.Context, conn *pgx.Conn, exclude ...string) ([]string, error) {
 	if len(exclude) == 0 {
-		exclude = append(exclude, "")
+		exclude = utils.ManagedSchemas
 	}
-	rows, err := conn.Query(ctx, LIST_SCHEMAS, exclude)
+	exclude = LikeEscapeSchema(exclude)
+	rows, err := conn.Query(ctx, ListSchemas, exclude)
 	if err != nil {
 		return nil, errors.Errorf("failed to list schemas: %w", err)
 	}
+	// TODO: show detail and hint from pgconn.PgError
 	return pgxv5.CollectStrings(rows)
 }
 
diff --git a/internal/db/reset/templates/drop.sql b/internal/db/reset/templates/drop.sql
index fa44da33..d5583e39 100644
--- a/internal/db/reset/templates/drop.sql
+++ b/internal/db/reset/templates/drop.sql
@@ -33,12 +33,12 @@ begin
     execute format('drop table if exists %I.%I cascade', rec.relnamespace::regnamespace::name, rec.relname);
   end loop;
 
-  -- truncate auth tables
+  -- truncate tables in auth and migrations schema
   for rec in
     select *
     from pg_class c
     where
-      c.relnamespace::regnamespace::name = 'auth'
+      c.relnamespace::regnamespace::name in ('auth', 'supabase_migrations')
       and c.relkind = 'r'
   loop
     execute format('truncate %I.%I restart identity cascade', rec.relnamespace::regnamespace::name, rec.relname);
@@ -59,7 +59,9 @@ begin
   for rec in
     select *
     from pg_type t
-    where t.typnamespace::regnamespace::name = 'public'
+    where
+      t.typnamespace::regnamespace::name = 'public'
+      and typtype != 'b'
   loop
     execute format('drop type if exists %I.%I cascade', rec.typnamespace::regnamespace::name, rec.typname);
   end loop;
diff --git a/internal/db/reset/templates/list.sql b/internal/db/reset/templates/list.sql
new file mode 100644
index 00000000..67f40a3f
--- /dev/null
+++ b/internal/db/reset/templates/list.sql
@@ -0,0 +1,13 @@
+-- List user defined schemas, excluding
+--  Extension created schemas
+--  Supabase managed schemas
+select pn.nspname
+from pg_namespace pn
+left join pg_depend pd
+  on pd.objid = pn.oid
+join pg_roles r 
+  on pn.nspowner = r.oid
+where pd.deptype is null
+  and not pn.nspname like any($1)
+  and r.rolname != 'supabase_admin'
+order by pn.nspname
diff --git a/internal/projects/create/create.go b/internal/projects/create/create.go
index ac030131..bc651b41 100644
--- a/internal/projects/create/create.go
+++ b/internal/projects/create/create.go
@@ -73,14 +73,11 @@ func promptMissingParams(ctx context.Context, body *api.CreateProjectBody) error
 }
 
 func promptProjectName() (string, error) {
-	name, err := utils.NewConsole().PromptText("Enter your project name: ")
-	if err != nil {
-		return "", err
-	}
-	if len(name) == 0 {
-		return "", errors.New("project name cannot be empty")
+	title := "Enter your project name: "
+	if name := utils.NewConsole().PromptText(title); len(name) > 0 {
+		return name, nil
 	}
-	return name, nil
+	return "", errors.New("project name cannot be empty")
 }
 
 func promptOrgId(ctx context.Context) (string, error) {
diff --git a/internal/utils/console.go b/internal/utils/console.go
index 9e0a0979..ffafb425 100644
--- a/internal/utils/console.go
+++ b/internal/utils/console.go
@@ -7,23 +7,20 @@ import (
 	"os"
 	"strings"
 
-	"github.com/go-errors/errors"
 	"golang.org/x/term"
 )
 
 type Console struct {
 	IsTTY  bool
 	stdin  *bufio.Scanner
-	stdout io.Writer
-	stderr io.Writer
+	logger io.Writer
 }
 
 func NewConsole() Console {
 	return Console{
 		IsTTY:  term.IsTerminal(int(os.Stdin.Fd())),
 		stdin:  bufio.NewScanner(os.Stdin),
-		stdout: os.Stdout,
-		stderr: GetDebugLogger(),
+		logger: GetDebugLogger(),
 	}
 }
 
@@ -35,13 +32,10 @@ func (c Console) PromptYesNo(label string, def bool) bool {
 	}
 	labelWithChoice := fmt.Sprintf("%s [%s] ", label, choices)
 	// Any error will be handled as default value
-	if s, err := c.PromptText(labelWithChoice); err != nil {
-		fmt.Fprintln(c.stdout)
-		if !errors.Is(err, io.EOF) {
-			fmt.Fprintln(c.stderr, err)
+	if input := c.PromptText(labelWithChoice); len(input) > 0 {
+		if answer := parseYesNo(input); answer != nil {
+			return *answer
 		}
-	} else if answer := parseYesNo(s); answer != nil {
-		return *answer
 	}
 	return def
 }
@@ -58,19 +52,19 @@ func parseYesNo(s string) *bool {
 }
 
 // PromptText asks for input using the label.
-func (c Console) PromptText(label string) (string, error) {
+func (c Console) PromptText(label string) string {
 	fmt.Fprint(os.Stderr, label)
 	// Scan a single line from input or file
 	if !c.stdin.Scan() {
-		return "", errors.New(io.EOF)
+		fmt.Fprintln(c.logger, io.EOF)
 	}
 	if err := c.stdin.Err(); err != nil {
-		return "", errors.Errorf("failed to scan stdin: %w", err)
+		fmt.Fprintln(c.logger, err)
 	}
 	token := strings.TrimSpace(c.stdin.Text())
-	// Echo input from non-interactive terminal
+	// Echo input to stderr for non-interactive terminals
 	if !c.IsTTY {
-		fmt.Fprintln(c.stdout, token)
+		fmt.Fprintln(os.Stderr, token)
 	}
-	return token, nil
+	return token
 }
diff --git a/internal/utils/misc.go b/internal/utils/misc.go
index 63e44d63..f85c697a 100644
--- a/internal/utils/misc.go
+++ b/internal/utils/misc.go
@@ -41,7 +41,7 @@ const (
 	PgbouncerImage   = "bitnami/pgbouncer:1.20.1-debian-11-r39"
 	PgProveImage     = "supabase/pg_prove:3.36"
 	GotrueImage      = "supabase/gotrue:v2.145.0"
-	RealtimeImage    = "supabase/realtime:v2.28.23"
+	RealtimeImage    = "supabase/realtime:v2.28.32"
 	StorageImage     = "supabase/storage-api:v1.0.6"
 	LogflareImage    = "supabase/logflare:1.4.0"
 	// Should be kept in-sync with EdgeRuntimeImage
@@ -111,9 +111,27 @@ var (
 		"information_schema",
 		"pg_*", // Wildcard pattern follows pg_dump
 	}
-	SystemSchemas = append([]string{
+	// Initialised by postgres image and owned by postgres role
+	ManagedSchemas = append([]string{
+		"pgbouncer",
+		"pgsodium",
+		"pgtle",
+		"supabase_migrations",
+		"vault",
+	}, PgSchemas...)
+	InternalSchemas = append([]string{
+		"auth",
+		"extensions",
+		"pgbouncer",
+		"realtime",
+		"_realtime",
+		"storage",
+		"_analytics",
+		"supabase_functions",
+		"supabase_migrations",
 		// Owned by extensions
 		"cron",
+		"dbdev",
 		"graphql",
 		"graphql_public",
 		"net",
@@ -128,17 +146,6 @@ var (
 		"topology",
 		"vault",
 	}, PgSchemas...)
-	InternalSchemas = append([]string{
-		"auth",
-		"extensions",
-		"pgbouncer",
-		"realtime",
-		"_realtime",
-		"storage",
-		"_analytics",
-		"supabase_functions",
-		"supabase_migrations",
-	}, SystemSchemas...)
 	ReservedRoles = []string{
 		"anon",
 		"authenticated",


Test patch:
diff --git a/internal/db/diff/diff_test.go b/internal/db/diff/diff_test.go
index 3843f708..c89761fd 100644
--- a/internal/db/diff/diff_test.go
+++ b/internal/db/diff/diff_test.go
@@ -35,27 +35,10 @@ var dbConfig = pgconn.Config{
 }
 
 var escapedSchemas = []string{
-	"auth",
 	"pgbouncer",
-	"realtime",
-	`\_realtime`,
-	"storage",
-	`\_analytics`,
-	`supabase\_functions`,
-	`supabase\_migrations`,
-	"cron",
-	"graphql",
-	`graphql\_public`,
-	"net",
 	"pgsodium",
-	`pgsodium\_masks`,
 	"pgtle",
-	"repack",
-	"tiger",
-	`tiger\_data`,
-	`timescaledb\_%`,
-	`\_timescaledb\_%`,
-	"topology",
+	`supabase\_migrations`,
 	"vault",
 	`information\_schema`,
 	`pg\_%`,
@@ -129,7 +112,7 @@ func TestRun(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(reset.LIST_SCHEMAS, escapedSchemas).
+		conn.Query(reset.ListSchemas, escapedSchemas).
 			ReplyError(pgerrcode.DuplicateTable, `relation "test" already exists`)
 		// Run test
 		err := Run(context.Background(), []string{}, "", dbConfig, DiffSchemaMigra, fsys, conn.Intercept)
@@ -355,24 +338,6 @@ At statement 0: create schema public`)
 	})
 }
 
-func TestUserSchema(t *testing.T) {
-	// Setup mock postgres
-	conn := pgtest.NewConn()
-	defer conn.Close(t)
-	conn.Query(reset.LIST_SCHEMAS, escapedSchemas).
-		Reply("SELECT 1", []interface{}{"test"})
-	// Connect to mock
-	ctx := context.Background()
-	mock, err := utils.ConnectByConfig(ctx, dbConfig, conn.Intercept)
-	require.NoError(t, err)
-	defer mock.Close(ctx)
-	// Run test
-	schemas, err := LoadUserSchemas(ctx, mock)
-	// Check error
-	assert.NoError(t, err)
-	assert.ElementsMatch(t, []string{"test"}, schemas)
-}
-
 func TestDropStatements(t *testing.T) {
 	drops := findDropStatements("create table t(); drop table t; alter table t drop column c")
 	assert.Equal(t, []string{"drop table t", "alter table t drop column c"}, drops)
diff --git a/internal/db/pull/pull_test.go b/internal/db/pull/pull_test.go
index fba4fa1a..95e2c603 100644
--- a/internal/db/pull/pull_test.go
+++ b/internal/db/pull/pull_test.go
@@ -31,27 +31,10 @@ var dbConfig = pgconn.Config{
 }
 
 var escapedSchemas = []string{
-	"auth",
 	"pgbouncer",
-	"realtime",
-	`\_realtime`,
-	"storage",
-	`\_analytics`,
-	`supabase\_functions`,
-	`supabase\_migrations`,
-	"cron",
-	"graphql",
-	`graphql\_public`,
-	"net",
 	"pgsodium",
-	`pgsodium\_masks`,
 	"pgtle",
-	"repack",
-	"tiger",
-	`tiger\_data`,
-	`timescaledb\_%`,
-	`\_timescaledb\_%`,
-	"topology",
+	`supabase\_migrations`,
 	"vault",
 	`information\_schema`,
 	`pg\_%`,
@@ -195,7 +178,7 @@ func TestPullSchema(t *testing.T) {
 		defer conn.Close(t)
 		conn.Query(list.LIST_MIGRATION_VERSION).
 			Reply("SELECT 1", []interface{}{"0"}).
-			Query(reset.LIST_SCHEMAS, escapedSchemas).
+			Query(reset.ListSchemas, escapedSchemas).
 			ReplyError(pgerrcode.DuplicateTable, `relation "test" already exists`)
 		// Connect to mock
 		ctx := context.Background()
diff --git a/internal/db/reset/reset_test.go b/internal/db/reset/reset_test.go
index 6841dbf4..9728bac4 100644
--- a/internal/db/reset/reset_test.go
+++ b/internal/db/reset/reset_test.go
@@ -304,28 +304,12 @@ func TestRestartDatabase(t *testing.T) {
 }
 
 var escapedSchemas = []string{
-	"public",
-	"auth",
 	"extensions",
+	"public",
 	"pgbouncer",
-	"realtime",
-	`\_realtime`,
-	"storage",
-	`\_analytics`,
-	`supabase\_functions`,
-	"cron",
-	"graphql",
-	`graphql\_public`,
-	"net",
 	"pgsodium",
-	`pgsodium\_masks`,
 	"pgtle",
-	"repack",
-	"tiger",
-	`tiger\_data`,
-	`timescaledb\_%`,
-	`\_timescaledb\_%`,
-	"topology",
+	`supabase\_migrations`,
 	"vault",
 	`information\_schema`,
 	`pg\_%`,
@@ -346,7 +330,7 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(LIST_SCHEMAS, escapedSchemas).
+		conn.Query(ListSchemas, escapedSchemas).
 			Reply("SELECT 1", []interface{}{"private"}).
 			Query("DROP SCHEMA IF EXISTS private CASCADE").
 			Reply("DROP SCHEMA").
@@ -373,7 +357,7 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(LIST_SCHEMAS, escapedSchemas).
+		conn.Query(ListSchemas, escapedSchemas).
 			ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation information_schema")
 		// Run test
 		err := resetRemote(context.Background(), "", dbConfig, fsys, conn.Intercept)
@@ -387,7 +371,7 @@ func TestResetRemote(t *testing.T) {
 		// Setup mock postgres
 		conn := pgtest.NewConn()
 		defer conn.Close(t)
-		conn.Query(LIST_SCHEMAS, escapedSchemas).
+		conn.Query(ListSchemas, escapedSchemas).
 			Reply("SELECT 0").
 			Query(dropObjects).
 			ReplyError(pgerrcode.InsufficientPrivilege, "permission denied for relation supabase_migrations")