Skip to content

Commit

Permalink
config: load config from module root
Browse files Browse the repository at this point in the history
Also fix the configuration loading order.
  • Loading branch information
k3rn31 committed Aug 9, 2022
1 parent 84c6887 commit ad841d1
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 9 deletions.
31 changes: 30 additions & 1 deletion configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,27 +110,56 @@ func arePathsNotSet(cPaths []string) bool {
func defaultConfigPaths() []string {
result := make([]string, 0, 4)

result = append(result, ".")
// First global config
if runtime.GOOS != windowsOs {
result = append(result, "/etc/gremlins")
}

// Then $XDG_CONFIG_HOME
xchLocation, _ := homedir.Expand("~/.config")
if x := os.Getenv(xdgConfigHomeKey); x != "" {
xchLocation = x
}
xchLocation = filepath.Join(xchLocation, "gremlins", "gremlins")
result = append(result, xchLocation)

// Then $HOME
homeLocation, err := homedir.Expand("~/.gremlins")
if err != nil {
return result
}
result = append(result, homeLocation)

// Then the Go module root
if root := findModuleRoot(); root != "" {
result = append(result, root)
}

// Finally the current folder
result = append(result, ".")

return result
}

func findModuleRoot() string {
// This function is duplicated from internal/gomodule. We should find a way
// to use here gomodule. The problem is the point of initialization, because
// configuration is initialised before gomodule.
path, _ := os.Getwd()
for {
if fi, err := os.Stat(filepath.Join(path, "go.mod")); err == nil && !fi.IsDir() {
return path
}
d := filepath.Dir(path)
if d == path {
break
}
path = d
}

return ""
}

var mutex sync.RWMutex

// Set offers synchronised access to Viper.
Expand Down
48 changes: 43 additions & 5 deletions configuration/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package configuration

import (
"os"
"path/filepath"
"runtime"
"testing"
Expand All @@ -34,7 +35,6 @@ type envEntry struct {
}

func TestConfiguration(t *testing.T) {

testCases := []struct {
wantedConfig map[string]interface{}
name string
Expand Down Expand Up @@ -130,12 +130,31 @@ func TestConfigPaths(t *testing.T) {
home, _ := homedir.Dir()

t.Run("it lookups in default locations", func(t *testing.T) {
oldDir, _ := os.Getwd()
_ = os.Chdir("testdata/config1")
defer func(dir string) {
_ = os.Chdir(dir)
}(oldDir)

var want []string
want = append(want, ".")

// First global
if runtime.GOOS != "windows" {
want = append(want, "/etc/gremlins")
}
want = append(want, filepath.Join(home, ".config", "gremlins", "gremlins"), filepath.Join(home, ".gremlins"))

// Then $XDG_CONFIG_HOME and $HOME
want = append(want,
filepath.Join(home, ".config", "gremlins", "gremlins"),
filepath.Join(home, ".gremlins"),
)

// Then module root
moduleRoot, _ := os.Getwd()
want = append(want, moduleRoot)

// Last current folder
want = append(want, ".")

got := defaultConfigPaths()

Expand All @@ -145,14 +164,33 @@ func TestConfigPaths(t *testing.T) {
})

t.Run("when XDG_CONFIG_HOME is set, it lookups in that locations", func(t *testing.T) {
oldDir, _ := os.Getwd()
_ = os.Chdir("testdata/config1")
defer func(dir string) {
_ = os.Chdir(dir)
}(oldDir)

customPath := filepath.Join("my", "custom", "path")
t.Setenv("XDG_CONFIG_HOME", customPath)

var want []string
want = append(want, ".")

// First global
if runtime.GOOS != "windows" {
want = append(want, "/etc/gremlins")
}
want = append(want, filepath.Join(customPath, "gremlins", "gremlins"), filepath.Join(home, ".gremlins"))

// Then $XDG_CONFIG_HOME and $HOME
want = append(want,
filepath.Join(customPath, "gremlins", "gremlins"),
filepath.Join(home, ".gremlins"))

// Then Go module root
moduleRoot, _ := os.Getwd()
want = append(want, moduleRoot)

// Last the current directory
want = append(want, ".")

got := defaultConfigPaths()

Expand Down
1 change: 1 addition & 0 deletions configuration/testdata/config1/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module example.com
7 changes: 4 additions & 3 deletions docs/docs/usage/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ Gremlins can be configured with a configuration file.
The configuration file can be placed in (in order of precedence)

1. `./.gremlins.yaml` (the current directory)
2. `/etc/gremlins/gremlins.yaml`
3. `$XDG_CONFIG_HOME/gremlins/gremlins.yaml`
4. `$HOME/.gremlins.yaml`
2. The module root
3. `/etc/gremlins/.gremlins.yaml`
4. `$XDG_CONFIG_HOME/gremlins/.gremlins.yaml`
5. `$HOME/.gremlins.yaml`

!!! hint
`XDG_CONFIG_HOME` is usually `~/.config`.
Expand Down

0 comments on commit ad841d1

Please sign in to comment.