From 870be22492e0300f5da1232d5806142bc48b0b82 Mon Sep 17 00:00:00 2001 From: Ben Moskovitz Date: Tue, 3 Dec 2024 13:03:46 +1100 Subject: [PATCH] Environment Variable config (#408) * Upgrade Go to 1.23.3 * Allow configuring API token and org slug via environment variable * Allow configuring REST API endpoint by environment variable --------- Co-authored-by: Ben McNicholl --- go.mod | 4 ++-- internal/config/config.go | 49 ++++++++++++++++++++++++-------------- pkg/cmd/factory/factory.go | 1 + 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 55f3b63..d9898e0 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/buildkite/cli/v3 -go 1.22 +go 1.23 -toolchain go1.22.5 +toolchain go1.23.3 require ( github.com/AlecAivazis/survey/v2 v2.3.7 diff --git a/internal/config/config.go b/internal/config/config.go index 6af6172..753c106 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -8,11 +8,14 @@ package config import ( "errors" "fmt" + "maps" "os" "path/filepath" "runtime" + "slices" "github.com/buildkite/cli/v3/internal/pipeline" + "github.com/buildkite/go-buildkite/v4" "github.com/go-git/go-git/v5" "github.com/spf13/afero" "github.com/spf13/viper" @@ -20,10 +23,11 @@ import ( const ( DefaultGraphQLEndpoint = "https://graphql.buildkite.com/v1" - appData = "AppData" - configFilePath = "bk.yaml" - localConfigFilePath = "." + configFilePath - xdgConfigHome = "XDG_CONFIG_HOME" + + appData = "AppData" + configFilePath = "bk.yaml" + localConfigFilePath = "." + configFilePath + xdgConfigHome = "XDG_CONFIG_HOME" ) // Config contains the configuration for the currently selected organization @@ -86,6 +90,7 @@ func New(fs afero.Fs, repo *git.Repository) *Config { // This will search for configuration in that order. func (conf *Config) OrganizationSlug() string { return firstNonEmpty( + os.Getenv("BUILDKITE_ORGANIZATION_SLUG"), conf.localConfig.GetString("selected_org"), conf.userConfig.GetString("selected_org"), ) @@ -101,7 +106,10 @@ func (conf *Config) SelectOrganization(org string) error { func (conf *Config) APIToken() string { slug := conf.OrganizationSlug() key := fmt.Sprintf("organizations.%s.api_token", slug) - return conf.userConfig.GetString(key) + return firstNonEmpty( + os.Getenv("BUILDKITE_API_TOKEN"), + conf.userConfig.GetString(key), + ) } // SetTokenForOrg sets the token for the given org in the user configuration file. Tokens are not stored in the local @@ -114,11 +122,11 @@ func (conf *Config) SetTokenForOrg(org, token string) error { func (conf *Config) ConfiguredOrganizations() []string { m := conf.userConfig.GetStringMap("organizations") - keys := make([]string, 0, len(m)) - for k := range m { - keys = append(keys, k) + orgs := slices.Collect(maps.Keys(m)) + if o := os.Getenv("BUILDKITE_ORGANIZATION_SLUG"); o != "" { + orgs = append(orgs, o) } - return keys + return orgs } func (conf *Config) GetGraphQLEndpoint() string { @@ -129,10 +137,17 @@ func (conf *Config) GetGraphQLEndpoint() string { return DefaultGraphQLEndpoint } +func (conf *Config) RESTAPIEndpoint() string { + value := os.Getenv("BUILDKITE_REST_API_ENDPOINT") + if value != "" { + return value + } + + return buildkite.DefaultBaseURL +} + func (conf *Config) HasConfiguredOrganization(slug string) bool { - m := conf.userConfig.GetStringMap("organizations") - _, ok := m[slug] - return ok + return slices.Contains(conf.ConfiguredOrganizations(), slug) } // PreferredPipelines will retrieve the list of pipelines from local configuration @@ -169,16 +184,14 @@ func (conf *Config) SetPreferredPipelines(pipelines []pipeline.Pipeline) error { return conf.localConfig.WriteConfig() } -func firstNonEmpty[T comparable](t ...T) T { - var empty T - - for _, k := range t { - if k != empty { +func firstNonEmpty(s ...string) string { + for _, k := range s { + if k != "" { return k } } - return empty + return "" } // Config path precedence: XDG_CONFIG_HOME, AppData (windows only), HOME. diff --git a/pkg/cmd/factory/factory.go b/pkg/cmd/factory/factory.go index 0e38fb6..deed220 100644 --- a/pkg/cmd/factory/factory.go +++ b/pkg/cmd/factory/factory.go @@ -40,6 +40,7 @@ func New(version string) (*Factory, error) { repo, _ := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true, EnableDotGitCommonDir: true}) conf := config.New(nil, repo) buildkiteClient, err := buildkite.NewOpts( + buildkite.WithBaseURL(conf.RESTAPIEndpoint()), buildkite.WithTokenAuth(conf.APIToken()), buildkite.WithUserAgent(userAgent), )