diff --git a/cmd/root.go b/cmd/root.go index f7caa54fd..d3ef3fce9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -12,7 +12,6 @@ import ( "github.com/getsentry/sentry-go" "github.com/go-errors/errors" - "github.com/mitchellh/mapstructure" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -223,18 +222,8 @@ func recoverAndExit() { func init() { cobra.OnInitialize(func() { - // Allow overriding config object with automatic env - // Ref: https://github.com/spf13/viper/issues/761 - envKeysMap := map[string]interface{}{} - dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ - Result: &envKeysMap, - IgnoreUntaggedFields: true, - }) - cobra.CheckErr(err) - cobra.CheckErr(dec.Decode(utils.Config)) - cobra.CheckErr(viper.MergeConfigMap(envKeysMap)) viper.SetEnvPrefix("SUPABASE") - viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) viper.AutomaticEnv() }) diff --git a/pkg/config/config.go b/pkg/config/config.go index 3bf566bb1..8914dcac0 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -28,6 +28,7 @@ import ( "github.com/go-errors/errors" "github.com/golang-jwt/jwt/v5" "github.com/joho/godotenv" + "github.com/mitchellh/mapstructure" "github.com/spf13/viper" "golang.org/x/mod/semver" @@ -136,13 +137,13 @@ type ( EdgeRuntime edgeRuntime `toml:"edge_runtime"` Functions FunctionConfig `toml:"functions"` Analytics analytics `toml:"analytics"` - Experimental experimental `toml:"experimental" mapstructure:"-"` + Experimental experimental `toml:"experimental"` } config struct { - baseConfig - Overrides map[string]interface{} `toml:"remotes"` - Remotes map[string]baseConfig `toml:"-"` + baseConfig `mapstructure:",squash"` + Overrides map[string]interface{} `toml:"remotes"` + Remotes map[string]baseConfig `toml:"-"` } db struct { @@ -587,6 +588,29 @@ func (c *config) Eject(w io.Writer) error { return nil } +func (c *config) loadFromEnv() error { + // Allow overriding base config object with automatic env + // Ref: https://github.com/spf13/viper/issues/761 + envKeysMap := map[string]interface{}{} + if dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + Result: &envKeysMap, + IgnoreUntaggedFields: true, + }); err != nil { + return errors.Errorf("failed to create decoder: %w", err) + } else if err := dec.Decode(c.baseConfig); err != nil { + return errors.Errorf("failed to decode env: %w", err) + } + v := viper.New() + v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + v.AutomaticEnv() + if err := v.MergeConfigMap(envKeysMap); err != nil { + return errors.Errorf("failed to merge config: %w", err) + } else if err := v.Unmarshal(c); err != nil { + return errors.Errorf("failed to parse env to config: %w", err) + } + return nil +} + func (c *config) Load(path string, fsys fs.FS) error { builder := NewPathBuilder(path) // Load default values @@ -614,9 +638,8 @@ func (c *config) Load(path string, fsys fs.FS) error { // Load secrets from .env file if err := loadDefaultEnv(); err != nil { return err - } - if err := viper.Unmarshal(c); err != nil { - return errors.Errorf("failed to parse env to config: %w", err) + } else if err := c.loadFromEnv(); err != nil { + return err } // Generate JWT tokens if len(c.Auth.AnonKey) == 0 { diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index af3ab9563..bef3df123 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -341,3 +341,15 @@ func TestLoadSeedPaths(t *testing.T) { assert.Empty(t, config.SqlPaths) }) } + +func TestLoadEnv(t *testing.T) { + t.Setenv("AUTH_JWT_SECRET", "test-secret") + t.Setenv("DB_ROOT_KEY", "test-root-key") + config := NewConfig() + // Run test + err := config.loadFromEnv() + // Check error + assert.NoError(t, err) + assert.Equal(t, "test-secret", config.Auth.JwtSecret) + assert.Equal(t, "test-root-key", config.Db.RootKey) +}