Skip to content
9 changes: 5 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/flags"
flagsutils "github.com/supabase/cli/internal/utils/flags"
"golang.org/x/mod/semver"
)

Expand Down Expand Up @@ -104,12 +104,12 @@ var (
}
ctx, _ = signal.NotifyContext(ctx, os.Interrupt)
if cmd.Flags().Lookup("project-ref") != nil {
if err := flags.ParseProjectRef(ctx, fsys); err != nil {
if err := flagsutils.ParseProjectRef(ctx, fsys); err != nil {
return err
}
}
}
if err := flags.ParseDatabaseConfig(cmd.Flags(), fsys); err != nil {
if err := flagsutils.ParseDatabaseConfig(cmd.Flags(), fsys); err != nil {
return err
}
// Prepare context
Expand Down Expand Up @@ -231,6 +231,7 @@ func init() {
flags.String("workdir", "", "path to a Supabase project directory")
flags.Bool("experimental", false, "enable experimental features")
flags.String("network-id", "", "use the specified docker network instead of a generated one")
flags.StringVar(&flagsutils.ConfigFile, "config-file", "", "path to config file (default: supabase/config.toml)")
flags.Var(&utils.OutputFormat, "output", "output format of status variables")
flags.Var(&utils.DNSResolver, "dns-resolver", "lookup domain names using the specified resolver")
flags.BoolVar(&createTicket, "create-ticket", false, "create a support ticket for any CLI error")
Expand Down Expand Up @@ -263,6 +264,6 @@ func addSentryScope(scope *sentry.Scope) {
scope.SetContext("Services", imageToVersion)
scope.SetContext("Config", map[string]interface{}{
"Image Registry": utils.GetRegistry(),
"Project ID": flags.ProjectRef,
"Project ID": flagsutils.ProjectRef,
})
}
85 changes: 85 additions & 0 deletions internal/start/start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/supabase/cli/internal/testing/apitest"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/flags"
"github.com/supabase/cli/pkg/config"
"github.com/supabase/cli/pkg/pgtest"
"github.com/supabase/cli/pkg/storage"
Expand Down Expand Up @@ -91,6 +92,90 @@ func TestStartCommand(t *testing.T) {
assert.NoError(t, err)
assert.Empty(t, apitest.ListUnmatchedRequests())
})

t.Run("loads custom config path", func(t *testing.T) {
// Setup in-memory fs
fsys := afero.NewMemMapFs()
customPath := "custom/path/config.toml"
projectId := "test_project"

// Create directories and required files
require.NoError(t, fsys.MkdirAll("custom/path", 0755))
require.NoError(t, fsys.MkdirAll("supabase", 0755))
require.NoError(t, afero.WriteFile(fsys, "supabase/seed.sql", []byte(""), 0644))
require.NoError(t, afero.WriteFile(fsys, "supabase/roles.sql", []byte(""), 0644))

// Store original values
originalDbId := utils.DbId
originalConfigFile := flags.ConfigFile

// Restore original values after test
t.Cleanup(func() {
utils.DbId = originalDbId
flags.ConfigFile = originalConfigFile
gock.Off()
})

// Write config file
require.NoError(t, afero.WriteFile(fsys, customPath, []byte(`# Test configuration
project_id = "`+projectId+`"

[api]
enabled = true
port = 54331
schemas = ["public", "storage", "graphql_public"]
extra_search_path = ["public", "extensions"]
max_rows = 1000

[db]
port = 54332
shadow_port = 54330
major_version = 15

[studio]
port = 54333

[inbucket]
port = 54334

[storage]
file_size_limit = "50MiB"

[auth]
site_url = "http://localhost:54331"
additional_redirect_urls = ["http://localhost:54331"]
jwt_expiry = 3600
enable_signup = true`), 0644))

// Setup mock docker
require.NoError(t, apitest.MockDocker(utils.Docker))

// Mock container list check
gock.New(utils.Docker.DaemonHost()).
Get("/v" + utils.Docker.ClientVersion() + "/containers/json").
Reply(http.StatusOK).
JSON([]types.Container{})

// Mock container checks
utils.DbId = "supabase_db_" + projectId
gock.New(utils.Docker.DaemonHost()).
Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId + "/json").
Times(2).
Reply(http.StatusOK).
JSON(types.ContainerJSON{ContainerJSONBase: &types.ContainerJSONBase{
State: &types.ContainerState{
Running: true,
Health: &types.Health{Status: types.Healthy},
},
}})

// Set the custom config path
flags.ConfigFile = customPath
// Run test
err := Run(context.Background(), fsys, []string{}, false)
assert.NoError(t, err)
assert.Empty(t, apitest.ListUnmatchedRequests())
})
}

func TestDatabaseStart(t *testing.T) {
Expand Down
10 changes: 9 additions & 1 deletion internal/utils/flags/config_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ import (
"github.com/supabase/cli/internal/utils"
)

var ConfigFile string

func LoadConfig(fsys afero.Fs) error {
utils.Config.ProjectId = ProjectRef
if err := utils.Config.Load("", utils.NewRootFS(fsys)); err != nil {

configPath := ""
if ConfigFile != "" {
configPath = ConfigFile
}

if err := utils.Config.Load(configPath, utils.NewRootFS(fsys)); err != nil {
if errors.Is(err, os.ErrNotExist) {
utils.CmdSuggestion = fmt.Sprintf("Have you set up the project with %s?", utils.Aqua("supabase init"))
}
Expand Down