Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions internal/db/diff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ func TestRun(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, flags.LoadConfig(fsys))
origServiceRoleKey := utils.Config.Auth.ServiceRoleKey.Value
utils.Config.Auth.ServiceRoleKey.Value = ""
t.Cleanup(func() { utils.Config.Auth.ServiceRoleKey.Value = origServiceRoleKey })
// Setup mock docker
require.NoError(t, apitest.MockDocker(utils.Docker))
defer gock.OffAll()
Expand Down Expand Up @@ -69,9 +72,10 @@ func TestRun(t *testing.T) {
require.NoError(t, apitest.MockDockerLogs(utils.Docker, "test-migra", diff))
// Setup mock postgres
conn := pgtest.NewConn()
conn.Query(CREATE_TEMPLATE).
Reply("CREATE DATABASE")
defer conn.Close(t)
helper.MockVaultSetup(conn, "").
Query(CREATE_TEMPLATE).
Reply("CREATE DATABASE")
// Run test
err := Run(context.Background(), []string{"public"}, "file", dbConfig, DiffSchemaMigra, fsys, func(cc *pgx.ConnConfig) {
if cc.Host == dbConfig.Host {
Expand Down Expand Up @@ -121,6 +125,12 @@ func TestMigrateShadow(t *testing.T) {
utils.Config.Db.ShadowPort = 54320
utils.GlobalsSql = "create schema public"
utils.InitialSchemaPg14Sql = "create schema private"
origWebhookSchema := start.WebhookSchema
start.WebhookSchema = "create schema supabase_functions"
t.Cleanup(func() { start.WebhookSchema = origWebhookSchema })
origServiceRoleKey := utils.Config.Auth.ServiceRoleKey.Value
utils.Config.Auth.ServiceRoleKey.Value = ""
t.Cleanup(func() { utils.Config.Auth.ServiceRoleKey.Value = origServiceRoleKey })
// Setup in-memory fs
fsys := afero.NewMemMapFs()
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
Expand All @@ -133,6 +143,9 @@ func TestMigrateShadow(t *testing.T) {
Reply("CREATE SCHEMA").
Query(utils.InitialSchemaPg14Sql).
Reply("CREATE SCHEMA").
Query(start.WebhookSchema).
Reply("CREATE SCHEMA")
helper.MockVaultSetup(conn, "").
Query(CREATE_TEMPLATE).
Reply("CREATE DATABASE")
helper.MockMigrationHistory(conn).
Expand Down Expand Up @@ -277,6 +290,12 @@ create schema public`)
})

t.Run("throws error on failure to diff target", func(t *testing.T) {
origWebhookSchema := start.WebhookSchema
start.WebhookSchema = "create schema supabase_functions"
t.Cleanup(func() { start.WebhookSchema = origWebhookSchema })
origServiceRoleKey := utils.Config.Auth.ServiceRoleKey.Value
utils.Config.Auth.ServiceRoleKey.Value = ""
t.Cleanup(func() { utils.Config.Auth.ServiceRoleKey.Value = origServiceRoleKey })
// Setup in-memory fs
fsys := afero.NewMemMapFs()
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
Expand Down Expand Up @@ -312,6 +331,9 @@ create schema public`)
Reply("CREATE SCHEMA").
Query(utils.InitialSchemaPg14Sql).
Reply("CREATE SCHEMA").
Query(start.WebhookSchema).
Reply("CREATE SCHEMA")
helper.MockVaultSetup(conn, "").
Query(CREATE_TEMPLATE).
Reply("CREATE DATABASE")
helper.MockMigrationHistory(conn).
Expand Down
34 changes: 32 additions & 2 deletions internal/db/push/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles,
}
}
if len(pending) == 0 && len(seeds) == 0 && len(globals) == 0 {
if !dryRun {
if err := syncVaultSecrets(ctx, config, conn); err != nil {
return err
}
}
fmt.Println("Remote database is up to date.")
return nil
}
Expand All @@ -67,13 +72,18 @@ func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles,
fmt.Fprint(os.Stderr, confirmSeedAll(seeds))
}
} else {
var vaultSynced bool
if len(globals) > 0 {
msg := "Do you want to create custom roles in the database cluster?"
if shouldPush, err := utils.NewConsole().PromptYesNo(ctx, msg, true); err != nil {
return err
} else if !shouldPush {
return errors.New(context.Canceled)
}
if err := syncVaultSecrets(ctx, config, conn); err != nil {
return err
}
vaultSynced = true
if err := migration.SeedGlobals(ctx, globals, conn, afero.NewIOFS(fsys)); err != nil {
return err
}
Expand All @@ -85,8 +95,11 @@ func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles,
} else if !shouldPush {
return errors.New(context.Canceled)
}
if err := vault.UpsertVaultSecrets(ctx, utils.Config.Db.Vault, conn); err != nil {
return err
if !vaultSynced {
if err := syncVaultSecrets(ctx, config, conn); err != nil {
return err
}
vaultSynced = true
}
if err := migration.ApplyMigrations(ctx, pending, conn, afero.NewIOFS(fsys)); err != nil {
return err
Expand All @@ -101,6 +114,11 @@ func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles,
} else if !shouldPush {
return errors.New(context.Canceled)
}
if !vaultSynced {
if err := syncVaultSecrets(ctx, config, conn); err != nil {
return err
}
}
if err := migration.SeedData(ctx, seeds, conn, afero.NewIOFS(fsys)); err != nil {
return err
}
Expand All @@ -112,6 +130,18 @@ func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles,
return nil
}

func syncVaultSecrets(ctx context.Context, config pgconn.Config, conn *pgx.Conn) error {
secrets := utils.Config.Db.Vault
if utils.IsLocalDatabase(config) || len(flags.ProjectRef) > 0 {
var projectRef string
if !utils.IsLocalDatabase(config) {
projectRef = flags.ProjectRef
}
secrets = vault.WithEdgeFunctionSecrets(secrets, projectRef, utils.Config.Auth.ServiceRoleKey.Value)
}
return vault.UpsertVaultSecrets(ctx, secrets, conn)
}

func confirmPushAll(pending []string) (msg string) {
for _, path := range pending {
filename := filepath.Base(path)
Expand Down
36 changes: 29 additions & 7 deletions internal/db/push/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import (
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/supabase/cli/internal/testing/apitest"
"github.com/supabase/cli/internal/testing/fstest"
"github.com/supabase/cli/internal/testing/helper"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/flags"
"github.com/supabase/cli/pkg/migration"
"github.com/supabase/cli/pkg/pgtest"
)
Expand All @@ -29,11 +31,13 @@ var dbConfig = pgconn.Config{
}

func TestMigrationPush(t *testing.T) {
flags.ProjectRef = apitest.RandomProjectRef()

t.Run("dry run", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
require.NoError(t, afero.WriteFile(fsys, path, []byte(""), 0644))
require.NoError(t, afero.WriteFile(fsys, path, []byte(""), 0o644))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
Expand All @@ -46,13 +50,17 @@ func TestMigrationPush(t *testing.T) {
})

t.Run("ignores up to date", func(t *testing.T) {
origServiceRoleKey := utils.Config.Auth.ServiceRoleKey.Value
utils.Config.Auth.ServiceRoleKey.Value = ""
t.Cleanup(func() { utils.Config.Auth.ServiceRoleKey.Value = origServiceRoleKey })
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(migration.LIST_MIGRATION_VERSION).
Reply("SELECT 0")
helper.MockVaultSetup(conn, flags.ProjectRef)
// Run test
err := Run(context.Background(), false, false, false, false, dbConfig, fsys, conn.Intercept)
// Check error
Expand Down Expand Up @@ -89,15 +97,19 @@ func TestMigrationPush(t *testing.T) {
})

t.Run("throws error on push failure", func(t *testing.T) {
origServiceRoleKey := utils.Config.Auth.ServiceRoleKey.Value
utils.Config.Auth.ServiceRoleKey.Value = ""
t.Cleanup(func() { utils.Config.Auth.ServiceRoleKey.Value = origServiceRoleKey })
// Setup in-memory fs
fsys := afero.NewMemMapFs()
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
require.NoError(t, afero.WriteFile(fsys, path, []byte(""), 0644))
require.NoError(t, afero.WriteFile(fsys, path, []byte(""), 0o644))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(migration.LIST_MIGRATION_VERSION).
Reply("SELECT 0")
helper.MockVaultSetup(conn, flags.ProjectRef)
helper.MockMigrationHistory(conn).
Query("RESET ALL").
Reply("RESET").
Expand All @@ -112,16 +124,22 @@ func TestMigrationPush(t *testing.T) {
}

func TestPushAll(t *testing.T) {
flags.ProjectRef = apitest.RandomProjectRef()

t.Run("ignores missing roles and seed", func(t *testing.T) {
origServiceRoleKey := utils.Config.Auth.ServiceRoleKey.Value
utils.Config.Auth.ServiceRoleKey.Value = ""
t.Cleanup(func() { utils.Config.Auth.ServiceRoleKey.Value = origServiceRoleKey })
// Setup in-memory fs
fsys := afero.NewMemMapFs()
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644))
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0o644))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(migration.LIST_MIGRATION_VERSION).
Reply("SELECT 0")
helper.MockVaultSetup(conn, flags.ProjectRef)
helper.MockMigrationHistory(conn).
Query("RESET ALL").
Reply("RESET").
Expand All @@ -138,7 +156,7 @@ func TestPushAll(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644))
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0o644))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
Expand All @@ -154,7 +172,7 @@ func TestPushAll(t *testing.T) {
// Setup in-memory fs
fsys := &fstest.StatErrorFs{DenyPath: utils.CustomRolesPath}
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644))
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0o644))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
Expand All @@ -167,21 +185,25 @@ func TestPushAll(t *testing.T) {
})

t.Run("throws error on seed failure", func(t *testing.T) {
origServiceRoleKey := utils.Config.Auth.ServiceRoleKey.Value
utils.Config.Auth.ServiceRoleKey.Value = ""
t.Cleanup(func() { utils.Config.Auth.ServiceRoleKey.Value = origServiceRoleKey })
digest := hex.EncodeToString(sha256.New().Sum(nil))
seedPath := filepath.Join(utils.SupabaseDirPath, "seed.sql")
utils.Config.Db.Seed.SqlPaths = []string{seedPath}
// Setup in-memory fs
fsys := afero.NewMemMapFs()
require.NoError(t, afero.WriteFile(fsys, seedPath, []byte{}, 0644))
require.NoError(t, afero.WriteFile(fsys, seedPath, []byte{}, 0o644))
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644))
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0o644))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
conn.Query(migration.LIST_MIGRATION_VERSION).
Reply("SELECT 0").
Query(migration.SELECT_SEED_TABLE).
Reply("SELECT 0")
helper.MockVaultSetup(conn, flags.ProjectRef)
helper.MockMigrationHistory(conn).
Query("RESET ALL").
Reply("RESET").
Expand Down
3 changes: 2 additions & 1 deletion internal/db/reset/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/supabase/cli/internal/migration/repair"
"github.com/supabase/cli/internal/seed/buckets"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/flags"
"github.com/supabase/cli/pkg/migration"
)

Expand Down Expand Up @@ -251,7 +252,7 @@ func resetRemote(ctx context.Context, version string, config pgconn.Config, fsys
return err
}
defer conn.Close(context.Background())
return down.ResetAll(ctx, version, conn, fsys)
return down.ResetAll(ctx, version, flags.ProjectRef, false, conn, fsys)
}

func LikeEscapeSchema(schemas []string) (result []string) {
Expand Down
7 changes: 6 additions & 1 deletion internal/db/reset/reset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/supabase/cli/internal/db/start"
"github.com/supabase/cli/internal/testing/apitest"
"github.com/supabase/cli/internal/testing/fstest"
"github.com/supabase/cli/internal/testing/helper"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/pkg/pgtest"
"github.com/supabase/cli/pkg/storage"
Expand All @@ -28,7 +29,7 @@ func TestResetCommand(t *testing.T) {
utils.Config.Hostname = "127.0.0.1"
utils.Config.Db.Port = 5432

var dbConfig = pgconn.Config{
dbConfig := pgconn.Config{
Host: utils.Config.Hostname,
Port: utils.Config.Db.Port,
User: "admin",
Expand All @@ -39,6 +40,9 @@ func TestResetCommand(t *testing.T) {
t.Run("seeds storage after reset", func(t *testing.T) {
utils.DbId = "test-reset"
utils.Config.Db.MajorVersion = 15
origServiceRoleKey := utils.Config.Auth.ServiceRoleKey.Value
utils.Config.Auth.ServiceRoleKey.Value = ""
t.Cleanup(func() { utils.Config.Auth.ServiceRoleKey.Value = origServiceRoleKey })
// Setup in-memory fs
fsys := afero.NewMemMapFs()
// Setup mock docker
Expand Down Expand Up @@ -67,6 +71,7 @@ func TestResetCommand(t *testing.T) {
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
helper.MockVaultSetup(conn, "")
// Restarts services
utils.StorageId = "test-storage"
utils.GotrueId = "test-auth"
Expand Down
17 changes: 13 additions & 4 deletions internal/db/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var (
//go:embed templates/schema.sql
initialSchema string
//go:embed templates/webhook.sql
webhookSchema string
WebhookSchema string
//go:embed templates/_supabase.sql
_supabaseSchema string
//go:embed templates/restore.sh
Expand Down Expand Up @@ -94,7 +94,7 @@ cat <<'EOF' > /etc/postgresql-custom/pgsodium_root.key && \
cat <<'EOF' >> /etc/postgresql/postgresql.conf && \
docker-entrypoint.sh postgres -D /etc/postgresql ` + strings.Join(args, " ") + `
` + initialSchema + `
` + webhookSchema + `
` + WebhookSchema + `
` + _supabaseSchema + `
EOF
` + utils.Config.Db.RootKey.Value + `
Expand Down Expand Up @@ -248,7 +248,15 @@ func initSchema(ctx context.Context, conn *pgx.Conn, host string, w io.Writer) e
} else if err := file.ExecBatch(ctx, conn); err != nil {
return err
}
return InitSchema14(ctx, conn)
if err := InitSchema14(ctx, conn); err != nil {
return err
}
if file, err := migration.NewMigrationFromReader(strings.NewReader(WebhookSchema)); err != nil {
return err
} else if err := file.ExecBatch(ctx, conn); err != nil {
return err
}
return nil
}
return initSchema15(ctx, host)
}
Expand Down Expand Up @@ -372,8 +380,9 @@ func SetupDatabase(ctx context.Context, conn *pgx.Conn, host string, w io.Writer
if err := initSchema(ctx, conn, host, w); err != nil {
return err
}
secrets := vault.WithEdgeFunctionSecrets(utils.Config.Db.Vault, "", utils.Config.Auth.ServiceRoleKey.Value)
// Create vault secrets first so roles.sql can reference them
if err := vault.UpsertVaultSecrets(ctx, utils.Config.Db.Vault, conn); err != nil {
if err := vault.UpsertVaultSecrets(ctx, secrets, conn); err != nil {
return err
}
err := migration.SeedGlobals(ctx, []string{utils.CustomRolesPath}, conn, afero.NewIOFS(fsys))
Expand Down
Loading
Loading