Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prod deploy #2719

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
01256a1
feat: support remote config overrides (#2704)
sweatybridge Sep 24, 2024
11c5004
fix: disable security opts for db test on bitbucket runner (#2705)
avallete Sep 24, 2024
2ad2d33
fix: Bump studio to the latest image version 20240923 (#2706)
ivasilov Sep 24, 2024
bb28463
chore: use _supabase database for internals
avallete Sep 24, 2024
5e94687
chore: fix tests mocks
avallete Sep 24, 2024
5904062
Merge branch 'develop' into avallete/chore-create-new-supabase-manage…
avallete Sep 24, 2024
e6788f3
chore: add realtime schema as well
avallete Sep 24, 2024
76ef3d2
fix: make the start work for postgres 14 and 13
avallete Sep 24, 2024
fd04d07
feat: add custom seed path to config (#2702)
avallete Sep 25, 2024
edb664a
Merge branch 'develop' into avallete/chore-create-new-supabase-manage…
avallete Sep 25, 2024
371a163
chore: add bitbucket build canary badge
avallete Sep 25, 2024
d5a34fc
chore: add gitlab canary badge
avallete Sep 25, 2024
936f5df
chore: add bitbucket build canary badge (#2709)
avallete Sep 25, 2024
49fd57f
Merge branch 'develop' into avallete/chore-create-new-supabase-manage…
avallete Sep 25, 2024
1623aa9
fix: Bump up studio image (#2711)
filipecabaco Sep 26, 2024
2822808
Merge branch 'develop' into avallete/chore-create-new-supabase-manage…
avallete Sep 26, 2024
ccf214d
chore: restore realtime to postgres database
avallete Sep 27, 2024
e911718
chore: remove relatime migration
avallete Sep 27, 2024
3115143
Update internal/db/start/start.go
avallete Sep 27, 2024
b64a8c8
chore: use _supabase database for internals (#2707)
avallete Sep 27, 2024
c8e553f
fix: bump edge-runtime to 1.58.11 (#2718)
nyannyacha Oct 1, 2024
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Supabase CLI (v1)

[![Coverage Status](https://coveralls.io/repos/github/supabase/cli/badge.svg?branch=main)](https://coveralls.io/github/supabase/cli?branch=main)
[![Coverage Status](https://coveralls.io/repos/github/supabase/cli/badge.svg?branch=main)](https://coveralls.io/github/supabase/cli?branch=main) [![Bitbucket Pipelines](https://img.shields.io/bitbucket/pipelines/supabase-cli/setup-cli/master?style=flat-square&label=Bitbucket%20Canary)](https://bitbucket.org/supabase-cli/setup-cli/pipelines) [![Gitlab Pipeline Status](https://img.shields.io/gitlab/pipeline-status/sweatybridge%2Fsetup-cli?label=Gitlab%20Canary)
](https://gitlab.com/sweatybridge/setup-cli/-/pipelines)

[Supabase](https://supabase.io) is an open source Firebase alternative. We're building the features of Firebase using enterprise-grade open source tools.

Expand Down
2 changes: 1 addition & 1 deletion cmd/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ func init() {
pushFlags := dbPushCmd.Flags()
pushFlags.BoolVar(&includeAll, "include-all", false, "Include all migrations not found on remote history table.")
pushFlags.BoolVar(&includeRoles, "include-roles", false, "Include custom roles from "+utils.CustomRolesPath+".")
pushFlags.BoolVar(&includeSeed, "include-seed", false, "Include seed data from "+utils.SeedDataPath+".")
pushFlags.BoolVar(&includeSeed, "include-seed", false, "Include seed data from your config.")
pushFlags.BoolVar(&dryRun, "dry-run", false, "Print the migrations that would be applied, but don't actually apply them.")
pushFlags.String("db-url", "", "Pushes to the database specified by the connection string (must be percent-encoded).")
pushFlags.Bool("linked", true, "Pushes to the linked project.")
Expand Down
2 changes: 1 addition & 1 deletion cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func validateExcludedContainers(excludedContainers []string) {
// Sort the names list so it's easier to visually spot the one you looking for
sort.Strings(validContainers)
warning := fmt.Sprintf("%s The following container names are not valid to exclude: %s\nValid containers to exclude are: %s\n",
utils.Yellow("Warning:"),
utils.Yellow("WARNING:"),
utils.Aqua(strings.Join(invalidContainers, ", ")),
utils.Aqua(strings.Join(validContainers, ", ")))
fmt.Fprint(os.Stderr, warning)
Expand Down
1 change: 1 addition & 0 deletions internal/db/dump/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func dumpData(ctx context.Context, config pgconn.Config, schema, excludeTable []
// "storage",
// "supabase_functions",
"supabase_migrations",
// TODO: Remove in a few version in favor of _supabase internal db
"_analytics",
"_realtime",
"_supavisor",
Expand Down
6 changes: 5 additions & 1 deletion internal/db/push/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ func Run(ctx context.Context, dryRun, ignoreVersionMismatch bool, includeRoles,
fmt.Fprintln(os.Stderr, "Would push these migrations:")
fmt.Fprint(os.Stderr, utils.Bold(confirmPushAll(pending)))
if includeSeed {
fmt.Fprintln(os.Stderr, "Would seed data "+utils.Bold(utils.SeedDataPath)+"...")
seedPaths, err := utils.GetSeedFiles(fsys)
if err != nil {
return err
}
fmt.Fprintf(os.Stderr, "Would seed data %v...\n", seedPaths)
}
} else {
msg := fmt.Sprintf("Do you want to push these migrations to the remote database?\n%s\n", confirmPushAll(pending))
Expand Down
4 changes: 3 additions & 1 deletion internal/db/push/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ func TestPushAll(t *testing.T) {

t.Run("throws error on seed failure", func(t *testing.T) {
// Setup in-memory fs
fsys := &fstest.OpenErrorFs{DenyPath: utils.SeedDataPath}
seedPath := filepath.Join(utils.SupabaseDirPath, "seed.sql")
fsys := &fstest.OpenErrorFs{DenyPath: seedPath}
_, _ = fsys.Create(seedPath)
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
require.NoError(t, afero.WriteFile(fsys, path, []byte{}, 0644))
// Setup mock postgres
Expand Down
2 changes: 2 additions & 0 deletions internal/db/reset/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ func recreateDatabase(ctx context.Context, options ...func(*pgx.ConnConfig)) err
Statements: []string{
"DROP DATABASE IF EXISTS postgres WITH (FORCE)",
"CREATE DATABASE postgres WITH OWNER postgres",
"DROP DATABASE IF EXISTS _supabase WITH (FORCE)",
"CREATE DATABASE _supabase WITH OWNER postgres",
},
}
return sql.ExecBatch(ctx, conn)
Expand Down
13 changes: 10 additions & 3 deletions internal/db/reset/reset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ func TestRecreateDatabase(t *testing.T) {
Query("DROP DATABASE IF EXISTS postgres WITH (FORCE)").
Reply("DROP DATABASE").
Query("CREATE DATABASE postgres WITH OWNER postgres").
Reply("CREATE DATABASE").
Query("DROP DATABASE IF EXISTS _supabase WITH (FORCE)").
Reply("DROP DATABASE").
Query("CREATE DATABASE _supabase WITH OWNER postgres").
Reply("CREATE DATABASE")
// Run test
assert.NoError(t, recreateDatabase(context.Background(), conn.Intercept))
Expand Down Expand Up @@ -194,8 +198,11 @@ func TestRecreateDatabase(t *testing.T) {
Reply("DO").
Query("DROP DATABASE IF EXISTS postgres WITH (FORCE)").
ReplyError(pgerrcode.ObjectInUse, `database "postgres" is used by an active logical replication slot`).
Query("CREATE DATABASE postgres WITH OWNER postgres")
// Run test
Query("CREATE DATABASE postgres WITH OWNER postgres").
Query("DROP DATABASE IF EXISTS _supabase WITH (FORCE)").
Reply("DROP DATABASE").
Query("CREATE DATABASE _supabase WITH OWNER postgres").
Reply("CREATE DATABASE")
err := recreateDatabase(context.Background(), conn.Intercept)
// Check error
assert.ErrorContains(t, err, `ERROR: database "postgres" is used by an active logical replication slot (SQLSTATE 55006)`)
Expand Down Expand Up @@ -362,7 +369,7 @@ func TestResetRemote(t *testing.T) {
fsys := afero.NewMemMapFs()
path := filepath.Join(utils.MigrationsDir, "0_schema.sql")
require.NoError(t, afero.WriteFile(fsys, path, nil, 0644))
seedPath := filepath.Join(utils.SeedDataPath)
seedPath := filepath.Join(utils.SupabaseDirPath, "seed.sql")
// Will raise an error when seeding
require.NoError(t, afero.WriteFile(fsys, seedPath, []byte("INSERT INTO test_table;"), 0644))
// Setup mock postgres
Expand Down
10 changes: 9 additions & 1 deletion internal/db/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ var (
HealthTimeout = 120 * time.Second
//go:embed templates/schema.sql
initialSchema string
//go:embed templates/_supabase.sql
_supabaseSchema string
)

func Run(ctx context.Context, fsys afero.Fs) error {
Expand Down Expand Up @@ -83,6 +85,7 @@ func NewContainerConfig() container.Config {
},
Entrypoint: []string{"sh", "-c", `cat <<'EOF' > /etc/postgresql.schema.sql && cat <<'EOF' > /etc/postgresql-custom/pgsodium_root.key && docker-entrypoint.sh postgres -D /etc/postgresql
` + initialSchema + `
` + _supabaseSchema + `
EOF
` + utils.Config.Db.RootKey + `
EOF
Expand Down Expand Up @@ -122,7 +125,12 @@ func StartDatabase(ctx context.Context, fsys afero.Fs, w io.Writer, options ...f
},
}
if utils.Config.Db.MajorVersion <= 14 {
config.Entrypoint = nil
config.Entrypoint = []string{"sh", "-c", `
cat <<'EOF' > /docker-entrypoint-initdb.d/supabase_schema.sql
` + _supabaseSchema + `
EOF
docker-entrypoint.sh postgres -D /etc/postgresql
`}
hostConfig.Tmpfs = map[string]string{"/docker-entrypoint-initdb.d": ""}
}
// Creating volume will not override existing volume, so we must inspect explicitly
Expand Down
3 changes: 2 additions & 1 deletion internal/db/start/start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"net/http"
"os"
"path/filepath"
"testing"

"github.com/docker/docker/api/types"
Expand Down Expand Up @@ -60,7 +61,7 @@ func TestStartDatabase(t *testing.T) {
roles := "create role test"
require.NoError(t, afero.WriteFile(fsys, utils.CustomRolesPath, []byte(roles), 0644))
seed := "INSERT INTO employees(name) VALUES ('Alice')"
require.NoError(t, afero.WriteFile(fsys, utils.SeedDataPath, []byte(seed), 0644))
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.SupabaseDirPath, "seed.sql"), []byte(seed), 0644))
// Setup mock docker
require.NoError(t, apitest.MockDocker(utils.Docker))
defer gock.OffAll()
Expand Down
13 changes: 13 additions & 0 deletions internal/db/start/templates/_supabase.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CREATE DATABASE _supabase WITH OWNER postgres;

-- Switch to the newly created _supabase database
\c _supabase
-- Create schemas in _supabase database for
-- internals tools and reports to not overload user database
-- with non-user activity
CREATE SCHEMA IF NOT EXISTS _analytics;
ALTER SCHEMA _analytics OWNER TO postgres;

CREATE SCHEMA IF NOT EXISTS _supavisor;
ALTER SCHEMA _supavisor OWNER TO postgres;
\c postgres
6 changes: 0 additions & 6 deletions internal/db/start/templates/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ ALTER USER supabase_read_only_user WITH PASSWORD :'pgpass';
create schema if not exists _realtime;
alter schema _realtime owner to postgres;

create schema if not exists _analytics;
alter schema _analytics owner to postgres;

create schema if not exists _supavisor;
alter schema _supavisor owner to postgres;

BEGIN;

-- Create pg_net extension
Expand Down
18 changes: 2 additions & 16 deletions internal/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,14 @@ func Run(ctx context.Context, fsys afero.Fs, createVscodeSettings, createIntelli
return err
}

// 2. Create `seed.sql`.
if err := initSeed(fsys); err != nil {
return err
}

// 3. Append to `.gitignore`.
// 2. Append to `.gitignore`.
if utils.IsGitRepo() {
if err := updateGitIgnore(utils.GitIgnorePath, fsys); err != nil {
return err
}
}

// 4. Generate VS Code settings.
// 3. Generate VS Code settings.
if createVscodeSettings != nil {
if *createVscodeSettings {
return writeVscodeConfig(fsys)
Expand All @@ -77,15 +72,6 @@ func Run(ctx context.Context, fsys afero.Fs, createVscodeSettings, createIntelli
return nil
}

func initSeed(fsys afero.Fs) error {
f, err := fsys.OpenFile(utils.SeedDataPath, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return errors.Errorf("failed to create seed file: %w", err)
}
defer f.Close()
return nil
}

func updateGitIgnore(ignorePath string, fsys afero.Fs) error {
var contents []byte

Expand Down
13 changes: 0 additions & 13 deletions internal/init/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ func TestInitCommand(t *testing.T) {
exists, err = afero.Exists(fsys, utils.GitIgnorePath)
assert.NoError(t, err)
assert.True(t, exists)
// Validate generated seed.sql
exists, err = afero.Exists(fsys, utils.SeedDataPath)
assert.NoError(t, err)
assert.True(t, exists)
// Validate vscode settings file isn't generated
exists, err = afero.Exists(fsys, settingsPath)
assert.NoError(t, err)
Expand Down Expand Up @@ -70,15 +66,6 @@ func TestInitCommand(t *testing.T) {
assert.Error(t, Run(context.Background(), fsys, nil, nil, utils.InitParams{}))
})

t.Run("throws error on seed failure", func(t *testing.T) {
// Setup in-memory fs
fsys := &fstest.OpenErrorFs{DenyPath: utils.SeedDataPath}
// Run test
err := Run(context.Background(), fsys, nil, nil, utils.InitParams{})
// Check error
assert.ErrorIs(t, err, os.ErrPermission)
})

t.Run("creates vscode settings file", func(t *testing.T) {
// Setup in-memory fs
fsys := &afero.MemMapFs{}
Expand Down
8 changes: 4 additions & 4 deletions internal/migration/apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ func MigrateAndSeed(ctx context.Context, version string, conn *pgx.Conn, fsys af
}

func SeedDatabase(ctx context.Context, conn *pgx.Conn, fsys afero.Fs) error {
err := migration.SeedData(ctx, []string{utils.SeedDataPath}, conn, afero.NewIOFS(fsys))
if errors.Is(err, os.ErrNotExist) {
return nil
seedPaths, err := utils.GetSeedFiles(fsys)
if err != nil {
return err
}
return err
return migration.SeedData(ctx, seedPaths, conn, afero.NewIOFS(fsys))
}

func CreateCustomRoles(ctx context.Context, conn *pgx.Conn, fsys afero.Fs) error {
Expand Down
10 changes: 6 additions & 4 deletions internal/migration/apply/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestMigrateDatabase(t *testing.T) {
path := filepath.Join(utils.MigrationsDir, "0_test.sql")
sql := "create schema public"
require.NoError(t, afero.WriteFile(fsys, path, []byte(sql), 0644))
seedPath := filepath.Join(utils.SeedDataPath)
seedPath := filepath.Join(utils.SupabaseDirPath, "seed.sql")
// This will raise an error when seeding
require.NoError(t, afero.WriteFile(fsys, seedPath, []byte("INSERT INTO test_table;"), 0644))
// Setup mock postgres
Expand Down Expand Up @@ -82,7 +82,7 @@ func TestSeedDatabase(t *testing.T) {
fsys := afero.NewMemMapFs()
// Setup seed file
sql := "INSERT INTO employees(name) VALUES ('Alice')"
require.NoError(t, afero.WriteFile(fsys, utils.SeedDataPath, []byte(sql), 0644))
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.SupabaseDirPath, "seed.sql"), []byte(sql), 0644))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
Expand All @@ -100,7 +100,9 @@ func TestSeedDatabase(t *testing.T) {

t.Run("throws error on read failure", func(t *testing.T) {
// Setup in-memory fs
fsys := &fstest.OpenErrorFs{DenyPath: utils.SeedDataPath}
seedPath := filepath.Join(utils.SupabaseDirPath, "seed.sql")
fsys := &fstest.OpenErrorFs{DenyPath: seedPath}
_, _ = fsys.Create(seedPath)
// Run test
err := SeedDatabase(context.Background(), nil, fsys)
// Check error
Expand All @@ -112,7 +114,7 @@ func TestSeedDatabase(t *testing.T) {
fsys := afero.NewMemMapFs()
// Setup seed file
sql := "INSERT INTO employees(name) VALUES ('Alice')"
require.NoError(t, afero.WriteFile(fsys, utils.SeedDataPath, []byte(sql), 0644))
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.SupabaseDirPath, "seed.sql"), []byte(sql), 0644))
// Setup mock postgres
conn := pgtest.NewConn()
defer conn.Close(t)
Expand Down
6 changes: 3 additions & 3 deletions internal/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func run(p utils.Program, ctx context.Context, fsys afero.Fs, excludedContainers
// Start Logflare
if utils.Config.Analytics.Enabled && !isContainerExcluded(utils.Config.Analytics.Image, excluded) {
env := []string{
"DB_DATABASE=" + dbConfig.Database,
"DB_DATABASE=_supabase",
"DB_HOSTNAME=" + dbConfig.Host,
fmt.Sprintf("DB_PORT=%d", dbConfig.Port),
"DB_SCHEMA=_analytics",
Expand Down Expand Up @@ -228,7 +228,7 @@ func run(p utils.Program, ctx context.Context, fsys afero.Fs, excludedContainers
)
case config.LogflarePostgres:
env = append(env,
fmt.Sprintf("POSTGRES_BACKEND_URL=postgresql://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database),
fmt.Sprintf("POSTGRES_BACKEND_URL=postgresql://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, "_supabase"),
"POSTGRES_BACKEND_SCHEMA=_analytics",
)
}
Expand Down Expand Up @@ -1045,7 +1045,7 @@ EOF
"PORT=4000",
fmt.Sprintf("PROXY_PORT_SESSION=%d", portSession),
fmt.Sprintf("PROXY_PORT_TRANSACTION=%d", portTransaction),
fmt.Sprintf("DATABASE_URL=ecto://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database),
fmt.Sprintf("DATABASE_URL=ecto://%s:%s@%s:%d/%s", dbConfig.User, dbConfig.Password, dbConfig.Host, dbConfig.Port, "_supabase"),
"CLUSTER_POSTGRES=true",
"SECRET_KEY_BASE=" + utils.Config.Db.Pooler.SecretKeyBase,
"VAULT_ENC_KEY=" + utils.Config.Db.Pooler.EncryptionKey,
Expand Down
3 changes: 3 additions & 0 deletions internal/utils/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ func DockerStart(ctx context.Context, config container.Config, hostConfig contai
// Skip named volume for BitBucket pipeline
if os.Getenv("BITBUCKET_CLONE_DIR") != "" {
hostConfig.Binds = binds
// Bitbucket doesn't allow for --security-opt option to be set
// https://support.atlassian.com/bitbucket-cloud/docs/run-docker-commands-in-bitbucket-pipelines/#Full-list-of-restricted-commands
hostConfig.SecurityOpt = nil
} else {
// Create named volumes with labels
for _, name := range sources {
Expand Down
22 changes: 21 additions & 1 deletion internal/utils/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"regexp"
"sort"
"time"

"github.com/docker/docker/client"
Expand Down Expand Up @@ -148,7 +149,6 @@ var (
FallbackImportMapPath = filepath.Join(FunctionsDir, "import_map.json")
FallbackEnvFilePath = filepath.Join(FunctionsDir, ".env")
DbTestsDir = filepath.Join(SupabaseDirPath, "tests")
SeedDataPath = filepath.Join(SupabaseDirPath, "seed.sql")
CustomRolesPath = filepath.Join(SupabaseDirPath, "roles.sql")

ErrNotLinked = errors.Errorf("Cannot find project ref. Have you run %s?", Aqua("supabase link"))
Expand All @@ -157,6 +157,26 @@ var (
ErrNotRunning = errors.Errorf("%s is not running.", Aqua("supabase start"))
)

// Match the glob patterns from the config to get a deduplicated
// array of all migrations files to apply in the declared order.
func GetSeedFiles(fsys afero.Fs) ([]string, error) {
seedPaths := Config.Db.Seed.SqlPaths
var files []string
for _, pattern := range seedPaths {
fullPattern := filepath.Join(SupabaseDirPath, pattern)
matches, err := afero.Glob(fsys, fullPattern)
if err != nil {
return nil, errors.Errorf("failed to apply glob pattern for %w", err)
}
if len(matches) == 0 {
fmt.Fprintf(os.Stderr, "%s Your pattern %s matched 0 seed files.\n", Yellow("WARNING:"), pattern)
}
sort.Strings(matches)
files = append(files, matches...)
}
return RemoveDuplicates(files), nil
}

func GetCurrentTimestamp() string {
// Magic number: https://stackoverflow.com/q/45160822.
return time.Now().UTC().Format("20060102150405")
Expand Down
Loading
Loading