Skip to content

Commit

Permalink
Fix setting config from env with complex (e.g. YAML) strings
Browse files Browse the repository at this point in the history
So you can do

```
HUGO_OUTPUTS="home: [rss]"  hugo
```

And similar.

Fixes #11249
  • Loading branch information
bep committed Jul 16, 2023
1 parent 286821e commit c406fd3
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 6 deletions.
2 changes: 1 addition & 1 deletion config/allconfig/alldecoders.go
Expand Up @@ -150,7 +150,7 @@ var allDecoderSetups = map[string]decodeWeight{
key: "outputs",
decode: func(d decodeWeight, p decodeConfig) error {
defaults := createDefaultOutputFormats(p.c.OutputFormats.Config)
m := p.p.GetStringMap("outputs")
m := maps.CleanConfigStringMap(p.p.GetStringMap("outputs"))
p.c.Outputs = make(map[string][]string)
for k, v := range m {
s := types.ToStringSlicePreserveString(v)
Expand Down
16 changes: 12 additions & 4 deletions config/allconfig/load.go
Expand Up @@ -293,11 +293,19 @@ func (l configLoader) applyOsEnvOverrides(environ []string) error {
} else {
l.cfg.Set(env.Key, val)
}
} else if nestedKey != "" {
owner[nestedKey] = env.Value
} else {
// The container does not exist yet.
l.cfg.Set(strings.ReplaceAll(env.Key, delim, "."), env.Value)
if nestedKey != "" {
owner[nestedKey] = env.Value
} else {
var val any = env.Value
if _, ok := allDecoderSetups[env.Key]; ok {
// A map.
val, err = metadecoders.Default.UnmarshalStringTo(env.Value, map[string]interface{}{})
}
if err == nil {
l.cfg.Set(strings.ReplaceAll(env.Key, delim, "."), val)
}
}
}
}

Expand Down
115 changes: 115 additions & 0 deletions hugolib/config_test.go
Expand Up @@ -1419,3 +1419,118 @@ Home.
b.Assert(len(b.H.Sites), qt.Equals, 1)

}

func TestLoadConfigYamlEnvVar(t *testing.T) {

defaultEnv := []string{`HUGO_OUTPUTS=home: ['json']`}

runVariant := func(t testing.TB, files string, env []string) *IntegrationTestBuilder {
if env == nil {
env = defaultEnv
}

b := NewIntegrationTestBuilder(
IntegrationTestConfig{
T: t,
TxtarString: files,
Environ: env,
BuildCfg: BuildCfg{SkipRender: true},
},
).Build()

outputs := b.H.Configs.Base.Outputs
if env == nil {
home := outputs["home"]
b.Assert(home, qt.Not(qt.IsNil))
b.Assert(home, qt.DeepEquals, []string{"json"})
}

return b

}

t.Run("with empty slice", func(t *testing.T) {
t.Parallel()

files := `
-- hugo.toml --
baseURL = "https://example.com"
disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
[outputs]
home = ["html"]
`
b := runVariant(t, files, []string{`HUGO_OUTPUTS=section: []`})
outputs := b.H.Configs.Base.Outputs
b.Assert(outputs, qt.DeepEquals, map[string][]string{
"home": {"html"},
"page": {"html"},
"rss": {"rss"},
"section": nil,
"taxonomy": {"html", "rss"},
"term": {"html", "rss"},
})

})

t.Run("with existing outputs", func(t *testing.T) {
t.Parallel()

files := `
-- hugo.toml --
baseURL = "https://example.com"
disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
[outputs]
home = ["html"]
`

runVariant(t, files, nil)

})

{
t.Run("with existing outputs direct", func(t *testing.T) {
t.Parallel()

files := `
-- hugo.toml --
baseURL = "https://example.com"
disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
[outputs]
home = ["html"]
`
runVariant(t, files, []string{"HUGO_OUTPUTS_HOME=json"})

})
}

t.Run("without existing outputs", func(t *testing.T) {
t.Parallel()

files := `
-- hugo.toml --
baseURL = "https://example.com"
disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
`

runVariant(t, files, nil)

})

t.Run("without existing outputs direct", func(t *testing.T) {
t.Parallel()

files := `
-- hugo.toml --
baseURL = "https://example.com"
disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
`

runVariant(t, files, []string{"HUGO_OUTPUTS_HOME=json"})

})

}
3 changes: 2 additions & 1 deletion parser/metadecoders/decoder.go
Expand Up @@ -23,6 +23,7 @@ import (
"strings"

"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/maps"
"github.com/niklasfasching/go-org/org"

xml "github.com/clbanning/mxj/v2"
Expand Down Expand Up @@ -90,7 +91,7 @@ func (d Decoder) UnmarshalStringTo(data string, typ any) (any, error) {
switch typ.(type) {
case string:
return data, nil
case map[string]any:
case map[string]any, maps.Params:
format := d.FormatFromContentString(data)
return d.UnmarshalToMap([]byte(data), format)
case []any:
Expand Down

0 comments on commit c406fd3

Please sign in to comment.