Repository: supabase/cli
Pull request #211 (2022-03-30 23:41:14)

Fix/more stuff


Patch:
diff --git a/internal/functions/serve/serve.go b/internal/functions/serve/serve.go
index 28d0b1c6..e32543bc 100644
--- a/internal/functions/serve/serve.go
+++ b/internal/functions/serve/serve.go
@@ -38,6 +38,11 @@ func Run(envFilePath string, slug string) error {
 		if err := utils.ValidateFunctionSlug(slug); err != nil {
 			return err
 		}
+		if envFilePath != "" {
+			if _, err := os.ReadFile(envFilePath); err != nil {
+				return fmt.Errorf("Failed to read env file: %w", err)
+			}
+		}
 	}
 
 	// 2. Stop on SIGINT/SIGTERM.
@@ -116,9 +121,7 @@ func Run(envFilePath string, slug string) error {
 			// skip
 		} else {
 			envMap, err := godotenv.Read(envFilePath)
-			if errors.Is(err, os.ErrNotExist) {
-				// skip
-			} else if err != nil {
+			if err != nil {
 				return err
 			}
 			for name, value := range envMap {
diff --git a/internal/start/start.go b/internal/start/start.go
index 2f8f12d9..5fd2743a 100644
--- a/internal/start/start.go
+++ b/internal/start/start.go
@@ -32,15 +32,15 @@ func Run() error {
 		if err := utils.AssertSupabaseCliIsSetUp(); err != nil {
 			return err
 		}
-
 		if err := utils.AssertDockerIsRunning(); err != nil {
 			return err
 		}
-
 		if err := utils.LoadConfig(); err != nil {
 			return err
 		}
-
+		if err := utils.InterpolateEnvInConfig(); err != nil {
+			return err
+		}
 		if err := utils.AssertSupabaseStartIsRunning(); err == nil {
 			return errors.New(utils.Aqua("supabase start") + " is already running. Try running " + utils.Aqua("supabase stop") + " first.")
 		}
diff --git a/internal/utils/config.go b/internal/utils/config.go
index e1b69272..47626125 100644
--- a/internal/utils/config.go
+++ b/internal/utils/config.go
@@ -213,21 +213,6 @@ func LoadConfig() error {
 			Config.Auth.External = map[string]provider{}
 		}
 
-		maybeLoadEnv := func(s string) (string, error) {
-			matches := regexp.MustCompile(`^env\((.*)\)$`).FindStringSubmatch(s)
-			if len(matches) == 0 {
-				return s, nil
-			}
-
-			envName := matches[1]
-			value := os.Getenv(envName)
-			if value == "" {
-				return "", errors.New(`Error evaluating "env(` + envName + `)": environment variable ` + envName + " is unset.")
-			}
-
-			return value, nil
-		}
-
 		for _, ext := range authExternalProviders {
 			if _, ok := Config.Auth.External[ext]; !ok {
 				Config.Auth.External[ext] = provider{
@@ -235,33 +220,56 @@ func LoadConfig() error {
 					ClientId: "",
 					Secret:   "",
 				}
-			} else if Config.Auth.External[ext].Enabled {
-				if Config.Auth.External[ext].ClientId == "" {
-					return fmt.Errorf("Missing required field in config: auth.external.%s.client_id", ext)
-				} else {
-					v, err := maybeLoadEnv(Config.Auth.External[ext].ClientId)
-					if err != nil {
-						return err
-					}
-					Config.Auth.External[ext] = provider{
-						Enabled:  true,
-						ClientId: v,
-						Secret:   Config.Auth.External[ext].Secret,
-					}
+			}
+		}
+	}
+
+	return nil
+}
+
+func InterpolateEnvInConfig() error {
+	maybeLoadEnv := func(s string) (string, error) {
+		matches := regexp.MustCompile(`^env\((.*)\)$`).FindStringSubmatch(s)
+		if len(matches) == 0 {
+			return s, nil
+		}
+
+		envName := matches[1]
+		value := os.Getenv(envName)
+		if value == "" {
+			return "", errors.New(`Error evaluating "env(` + envName + `)": environment variable ` + envName + " is unset.")
+		}
+
+		return value, nil
+	}
+
+	for _, ext := range authExternalProviders {
+		if Config.Auth.External[ext].Enabled {
+			var clientId, secret string
+
+			if Config.Auth.External[ext].ClientId == "" {
+				return fmt.Errorf("Missing required field in config: auth.external.%s.client_id", ext)
+			} else {
+				v, err := maybeLoadEnv(Config.Auth.External[ext].ClientId)
+				if err != nil {
+					return err
 				}
-				if Config.Auth.External[ext].Secret == "" {
-					return fmt.Errorf("Missing required field in config: auth.external.%s.secret", ext)
-				} else {
-					v, err := maybeLoadEnv(Config.Auth.External[ext].Secret)
-					if err != nil {
-						return fmt.Errorf("failed to parse config file: %+v", err)
-					}
-					Config.Auth.External[ext] = provider{
-						Enabled:  true,
-						ClientId: Config.Auth.External[ext].ClientId,
-						Secret:   v,
-					}
+				clientId = v
+			}
+			if Config.Auth.External[ext].Secret == "" {
+				return fmt.Errorf("Missing required field in config: auth.external.%s.secret", ext)
+			} else {
+				v, err := maybeLoadEnv(Config.Auth.External[ext].Secret)
+				if err != nil {
+					return err
 				}
+				secret = v
+			}
+
+			Config.Auth.External[ext] = provider{
+				Enabled:  true,
+				ClientId: clientId,
+				Secret:   secret,
 			}
 		}
 	}


Test patch:
diff --git a/internal/utils/config_test.go b/internal/utils/config_test.go
index 90c3b08c..11fe3477 100644
--- a/internal/utils/config_test.go
+++ b/internal/utils/config_test.go
@@ -5,26 +5,26 @@ import (
 	"testing"
 )
 
-func TestConfigParsing(superTest *testing.T) {
-	superTest.Cleanup(func() {
-		if err := os.Remove("./supabase/config.toml"); err != nil {
+func TestConfigParsing(t *testing.T) {
+	t.Cleanup(func() {
+		if err := os.Remove("supabase/config.toml"); err != nil {
 			if !os.IsNotExist(err) {
-				superTest.Error(err)
+				t.Error(err)
 			}
 		}
-		if err := os.Remove("./supabase"); err != nil {
+		if err := os.Remove("supabase"); err != nil {
 			if !os.IsNotExist(err) {
-				superTest.Error(err)
+				t.Error(err)
 			}
 		}
 	})
 
-	if err := os.Mkdir("./supabase", 0777); err != nil {
-		superTest.Error(err)
-		superTest.FailNow()
+	if err := os.Mkdir("supabase", 0755); err != nil {
+		t.Error(err)
+		t.FailNow()
 	}
 
-	superTest.Run("classic config file", func(t *testing.T) {
+	t.Run("classic config file", func(t *testing.T) {
 		if err := WriteConfig(false); err != nil {
 			t.Error(err)
 			t.FailNow()
@@ -35,7 +35,7 @@ func TestConfigParsing(superTest *testing.T) {
 		}
 	})
 
-	superTest.Run("config file with environment variables", func(t *testing.T) {
+	t.Run("config file with environment variables", func(t *testing.T) {
 		if err := WriteConfig(true); err != nil {
 			t.Error(err)
 			t.FailNow()
@@ -47,6 +47,12 @@ func TestConfigParsing(superTest *testing.T) {
 			t.Error(err)
 			t.FailNow()
 		}
+		if err := InterpolateEnvInConfig(); err != nil {
+			t.Error(err)
+			t.FailNow()
+		}
+		t.Setenv("AZURE_CLIENT_ID", "hello")
+		t.Setenv("AZURE_SECRET", "this is cool")
 
 		if Config.Auth.External["azure"].ClientId != "hello" {
 			t.Errorf("unexpected value for key [ClientId]: %+v", Config.Auth.External["azure"])
@@ -59,13 +65,17 @@ func TestConfigParsing(superTest *testing.T) {
 		}
 	})
 
-	superTest.Run("config file with environment variables fails when unset", func(t *testing.T) {
+	t.Run("config file with environment variables fails when unset", func(t *testing.T) {
 		if err := WriteConfig(true); err != nil {
 			t.Error(err)
 			t.FailNow()
 		}
 
-		if err := LoadConfig(); err == nil {
+		if err := LoadConfig(); err != nil {
+			t.Error(err)
+			t.FailNow()
+		}
+		if err := InterpolateEnvInConfig(); err == nil {
 			t.Error("expected to fail")
 			t.FailNow()
 		}