diff --git a/pkg/config/config.go b/pkg/config/config.go index 6c339ec..69c0c71 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -58,6 +58,10 @@ func (c *Config) ValidateConfig() error { func Load(dir string, out io.Writer) (*Config, error) { cfg := InitEmptyConfig() + if err := env.Parse(cfg); err != nil { + return nil, err + } + err := parseConfigFiles(dir, out, func(dir string) error { return parseConfigFile(dir, cfg) }) @@ -65,8 +69,6 @@ func Load(dir string, out io.Writer) (*Config, error) { return nil, err } - err = env.Parse(cfg) - return cfg, err } @@ -282,13 +284,13 @@ func parseConfigFiles(dir string, out io.Writer, fn func(string) error) error { parent = filepath.Dir(parent) } - for i, file := range files { + for i, f := range files { if i == 0 { - _, _ = fmt.Fprintln(out, tml.Sprintf("Parsing config from file: '%s'", file)) + _, _ = fmt.Fprintln(out, tml.Sprintf("Parsing config from file: '%s'", f)) } else { - _, _ = fmt.Fprintln(out, tml.Sprintf("Merging with config from file: '%s'", file)) + _, _ = fmt.Fprintln(out, tml.Sprintf("Merging with config from file: '%s'", f)) } - if err := fn(file); err != nil { + if err := fn(f); err != nil { return err } } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index a359667..69b7d37 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -36,6 +36,81 @@ func teardown(tempDir string) { _ = os.RemoveAll(tempDir) } +func TestLoad_Env_Overrides_YAML(t *testing.T) { + os.Clearenv() + defer SetEnv("BUILDKITE_TOKEN", "test")() + + yaml := ` +ci: + buildkite: + organisation: example + token: abc +vcs: + github: + organisation: example + token: abc +` + file := filepath.Join(name, ".scaffold.yaml") + _ = ioutil.WriteFile(file, []byte(yaml), 0777) + defer func() { _ = os.Remove(file) }() + + out := &bytes.Buffer{} + + cfg, err := Load(name, out) + assert.NoError(t, err) + assert.NotNil(t, cfg) + assert.Equal(t, "test", cfg.CI.Buildkite.Token) +} + +func TestLoad_SubDir_Overrides_Dir(t *testing.T) { + os.Clearenv() + + yaml := ` +ci: + buildkite: + organisation: example + token: abc +vcs: + github: + organisation: example + token: abc +` + subYaml := ` +ci: + buildkite: + organisation: example + token: test +vcs: + github: + organisation: example + token: abc +` + file := filepath.Join(name, ".scaffold.yaml") + _ = ioutil.WriteFile(file, []byte(yaml), 0777) + defer func() { _ = os.Remove(file) }() + sub := filepath.Join(name, "sub") + _ = os.MkdirAll(sub, 0777) + defer func() { _ = os.RemoveAll(sub) }() + _ = ioutil.WriteFile(filepath.Join(sub, ".scaffold.yaml"), []byte(subYaml), 0777) + + out := &bytes.Buffer{} + + cfg, err := Load(sub, out) + assert.NoError(t, err) + assert.NotNil(t, cfg) + assert.Equal(t, "test", cfg.CI.Buildkite.Token) +} + +func TestParseConfigFile_Return_Error_For_Unreadable_File(t *testing.T) { + out := &bytes.Buffer{} + dir := filepath.Join(name, ".scaffold.yaml") + _ = os.MkdirAll(dir, 0777) + defer func() { _ = os.RemoveAll(dir) }() + + _, err := Load(name, out) + assert.EqualError(t, err, fmt.Sprintf("read %s: is a directory", dir)) +} + func TestValidateConfig_No_VCS_Configured(t *testing.T) { cfg := InitEmptyConfig() err := cfg.ValidateConfig() diff --git a/pkg/config/testing.go b/pkg/config/testing.go new file mode 100644 index 0000000..b6ed25d --- /dev/null +++ b/pkg/config/testing.go @@ -0,0 +1,12 @@ +// +build !prod + +package config + +import ( + "os" +) + +func SetEnv(key, value string) func() { + _ = os.Setenv(key, value) + return func() { _ = os.Unsetenv(key) } +} diff --git a/pkg/scaffold_test.go b/pkg/scaffold_test.go index 61e2d1f..1fb5d26 100644 --- a/pkg/scaffold_test.go +++ b/pkg/scaffold_test.go @@ -102,6 +102,32 @@ vcs: assert.Equal(t, fmt.Sprintf("\x1b[0mParsing config from file: \x1b[32m'%s'\x1b[39m\x1b[0m\n\x1b[0m\x1b[31mGET https://api.buildkite.com/v2/user: 401 Authentication required. Please supply a valid API Access Token: https://buildkite.com/docs/apis/rest-api#authentication\x1b[39m\x1b[0m\n", file), out.String()) } +func TestScaffold_Fails_For_Multiple_Configured_CIs(t *testing.T) { + defer SetEnv("GITLAB_GROUP", "test")() + defer SetEnv("GITLAB_TOKEN", "test")() + + yaml := ` +ci: + buildkite: + organisation: example + token: abc +vcs: + github: + organisation: example + token: abc +` + file := filepath.Join(name, ".scaffold.yaml") + _ = ioutil.WriteFile(file, []byte(yaml), 0777) + defer func() { _ = os.Remove(file) }() + + out := bytes.Buffer{} + + exitCode := Setup(name, &out, "project") + + assert.Equal(t, -3, exitCode) + assert.Equal(t, fmt.Sprintf("\x1b[0mParsing config from file: \x1b[32m'%s'\x1b[39m\x1b[0m\n\x1b[0m\x1b[31mscaffold CI already defined, please check configuration\x1b[39m\x1b[0m\n", file), out.String()) +} + func TestScaffold_Configure_Error(t *testing.T) { cfg := config.InitEmptyConfig() cfg.CurrentCI = &mockCi{configErr: errors.New("config error")}