-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SUP-1761 Implement local config pipeline resolver func (#234)
* SUP-1453 Allow local directory config override for default pipeline --------- Co-authored-by: Jarryd Tilbrook <jarryd@buildkite.com>
- Loading branch information
1 parent
73a628c
commit 00d6725
Showing
16 changed files
with
253 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
*.DS_STORE | ||
dist/ | ||
buildkite.yaml | ||
buildkite.yaml | ||
.bk.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package config | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/spf13/viper" | ||
) | ||
|
||
const ( | ||
DefaultPipelineConfigKey = "default_pipeline" | ||
PipelinesSlugConfigKey = "pipelines" | ||
) | ||
|
||
// LocalConfig contains the configuration for the "cached" pipelines | ||
// and the default selected pipeline | ||
// | ||
// config file format (yaml): | ||
// | ||
// default_pipeline: buildkite-1 | ||
// organizations: | ||
// buildkite | ||
// pipelines: | ||
// - buildkite-1 | ||
// - buildkite-2 | ||
// buildkite-oss | ||
// pipelines: | ||
// - buildkite-oss-1 | ||
// - buildkite-oss-2 | ||
type LocalConfig struct { | ||
DefaultPipeline string | ||
Organization string | ||
Pipelines []string | ||
V ViperLocalConfig | ||
} | ||
|
||
type ViperLocalConfig interface { | ||
Set(string, interface{}) | ||
GetStringMap(string) map[string]interface{} | ||
WriteConfig() error | ||
} | ||
|
||
func LoadLocalConfig(org string) *LocalConfig { | ||
|
||
v := viper.New() | ||
v.SetConfigFile(localConfigFile()) | ||
v.AddConfigPath(".") | ||
_ = v.ReadInConfig() | ||
|
||
default_pipeline := v.GetString(DefaultPipelineConfigKey) | ||
orgs := v.GetStringMap(OrganizationsSlugConfigKey) | ||
|
||
if _, ok := orgs[org]; ok { | ||
selectedOrgKey := fmt.Sprintf("%s.%s.%s", OrganizationsSlugConfigKey, org, PipelinesSlugConfigKey) | ||
selectedPipelines := v.GetStringSlice(selectedOrgKey) | ||
return &LocalConfig{ | ||
DefaultPipeline: default_pipeline, | ||
Organization: org, | ||
Pipelines: selectedPipelines, | ||
V: v, | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func (conf *LocalConfig) merge() { | ||
orgs := conf.V.GetStringMap(OrganizationsSlugConfigKey) | ||
orgs[conf.Organization] = map[string]interface{}{ | ||
PipelinesSlugConfigKey: conf.Pipelines, | ||
} | ||
conf.V.Set(OrganizationsSlugConfigKey, orgs) | ||
conf.V.Set(DefaultPipelineConfigKey, conf.DefaultPipeline) | ||
} | ||
|
||
// Save sets the current config values into viper and writes the config file | ||
func (conf *LocalConfig) Save() error { | ||
conf.V.Set(DefaultPipelineConfigKey, conf.DefaultPipeline) | ||
conf.merge() | ||
|
||
return conf.V.WriteConfig() | ||
} | ||
|
||
func localConfigFile() string { | ||
var path string | ||
if _, err := os.Stat(".bk.yaml"); err == nil { | ||
path = ".bk.yaml" | ||
} else if _, err := os.Stat(".bk.yml"); err == nil { | ||
path = ".bk.yml" | ||
} | ||
return path | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package config | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/spf13/viper" | ||
) | ||
|
||
func TestLocalConfig(t *testing.T) { | ||
t.Parallel() | ||
|
||
t.Run("empty viper adds current local config", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
v := viper.New() | ||
|
||
l := LocalConfig{ | ||
DefaultPipeline: "bk-1", | ||
Organization: "bk", | ||
Pipelines: []string{"bk-1"}, | ||
V: v, | ||
} | ||
|
||
l.merge() | ||
|
||
p := v.GetString(DefaultPipelineConfigKey) | ||
if len(p) == 0 { | ||
t.Error("should have default pipeline present") | ||
} | ||
|
||
m := v.GetStringMap(OrganizationsSlugConfigKey) | ||
if len(m) != 1 { | ||
t.Error("should have config items present") | ||
} | ||
if _, ok := m["bk"]; ok { | ||
switch m["bk"].(type) { | ||
case map[string]interface{}: | ||
pipelines := m["bk"].(map[string]interface{})[PipelinesSlugConfigKey].([]string) | ||
if len(pipelines) != 1 { | ||
t.Error("should have pipelines present") | ||
} | ||
return | ||
default: | ||
t.Error("incorrect type in config") | ||
} | ||
} else { | ||
t.Error("org is not present") | ||
} | ||
|
||
}) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package pipeline | ||
|
||
import "github.com/charmbracelet/huh" | ||
|
||
func RenderOptions(defaultPipeline string, pipelines []string) (string, error) { | ||
|
||
options := huh.NewOptions(pipelines...) | ||
|
||
if len(options) == 1 { | ||
options[0].Selected(true) | ||
} | ||
for i, opt := range options { | ||
if defaultPipeline == opt.Value { | ||
options[i] = opt.Selected(true) | ||
} | ||
} | ||
|
||
var choice string | ||
err := huh.NewForm( | ||
huh.NewGroup( | ||
huh.NewSelect[string](). | ||
Title("Select a pipeline"). | ||
Options(options...). | ||
Value(&choice), | ||
), | ||
). | ||
WithShowHelp(false). | ||
Run() | ||
|
||
return choice, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,45 @@ | ||
package resolver | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/buildkite/cli/v3/pkg/cmd/factory" | ||
"github.com/buildkite/cli/v3/internal/config" | ||
"github.com/buildkite/cli/v3/internal/pipeline" | ||
) | ||
|
||
func ResolveFromConfig(f *factory.Factory) ([]string, error) { | ||
func ResolveFromConfig(c *config.LocalConfig) PipelineResolverFn { | ||
return func() (*pipeline.Pipeline, error) { | ||
|
||
var localPipelines []string | ||
// check if there is a local config file | ||
err := f.LocalConfig.Read() | ||
if err != nil { | ||
fmt.Printf("Error reading local config: %s", err) | ||
return nil, err | ||
} | ||
// if there is a pipeline defined in the local config, return it | ||
if len(f.LocalConfig.Pipeline) > 0 { | ||
//assume pipelines are comma separated - final format TBD | ||
localPipelines = strings.Split(f.LocalConfig.Pipeline, ",") | ||
var pipelines []string | ||
var defaultPipeline string | ||
|
||
defaultPipeline = c.DefaultPipeline | ||
if defaultPipeline == "" && len(c.Pipelines) == 0 { | ||
return nil, nil | ||
} | ||
|
||
if defaultPipeline == "" && len(c.Pipelines) >= 1 { | ||
defaultPipeline = c.Pipelines[0] | ||
} | ||
|
||
defaultExists := false | ||
for _, opt := range c.Pipelines { | ||
if defaultPipeline == opt { | ||
defaultExists = true | ||
} | ||
pipelines = append(pipelines, opt) | ||
} | ||
|
||
if !defaultExists { //add default pipeline to the list of pipelines | ||
pipelines = append(pipelines, defaultPipeline) | ||
} | ||
|
||
selected, err := pipeline.RenderOptions(defaultPipeline, pipelines) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &pipeline.Pipeline{ | ||
Name: selected, | ||
Org: c.Organization, | ||
}, nil | ||
} | ||
return localPipelines, nil | ||
} |
Oops, something went wrong.