Skip to content

Commit

Permalink
read project name from env by default (#949)
Browse files Browse the repository at this point in the history
* read project name from env by default

* rebind env values to config
  • Loading branch information
xavdid-stripe committed Oct 31, 2022
1 parent 4b334a0 commit 7e58ee7
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 8 deletions.
39 changes: 34 additions & 5 deletions pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ var rootCmd = &cobra.Command{
// if getting the config errors, don't fail running the command
merchant, _ := Config.Profile.GetAccountID()
telemetryMetadata := stripe.GetEventMetadata(cmd.Context())
telemetryMetadata.SetCobraCommandContext(cmd)
telemetryMetadata.SetMerchant(merchant)
telemetryMetadata.SetUserAgent(useragent.GetEncodedUserAgent())
if telemetryMetadata != nil {
telemetryMetadata.SetCobraCommandContext(cmd)
telemetryMetadata.SetMerchant(merchant)
telemetryMetadata.SetUserAgent(useragent.GetEncodedUserAgent())
}

// plugins send their own telemetry due to having richer context than the CLI does
if !plugins.IsPluginCommand(cmd) {
Expand Down Expand Up @@ -106,7 +108,7 @@ func Execute(ctx context.Context) {
case requests.IsAPIKeyExpiredError(err):
fmt.Fprintln(os.Stderr, "The API key provided has expired. Obtain a new key from the Dashboard or run `stripe login` and try again.")
case isLoginRequiredError && projectNameFlag != "default":
fmt.Println("You provided the \"--project-name\" flag, but no config for that project was found. Please run `stripe login --project-name=`...")
fmt.Printf("You provided the project name \"%[1]s\" (either via the \"--project-name\" flag or the \"STRIPE_PROJECT_NAME\" environment variable), but no config for that project was found.\nPlease run `stripe login --project-name=%[1]s` to enable commands for this project.\n", projectNameFlag)
case isLoginRequiredError:
// capitalize first letter of error because linter
errRunes := []rune(errString)
Expand Down Expand Up @@ -137,8 +139,30 @@ func Execute(ctx context.Context) {
}
}

var keysToReBind []string

// ReBindKeys applies the value found in viper config to the cobra flag when viper has a value (possibly from env)
func ReBindKeys() {
for _, k := range keysToReBind {
if viper.IsSet(k) {
rootCmd.Flags().Set(k, viper.GetString(k))
}
}
}

// wraps viper's bindEnv and ensures we write values back to the Config
// value precedence is:
// 1. flag
// 2. env
// 3. default
func bindEnv(key, envKey string) {
viper.BindPFlag(key, rootCmd.PersistentFlags().Lookup(key))
viper.BindEnv(key, envKey)
keysToReBind = append(keysToReBind, key)
}

func init() {
cobra.OnInitialize(Config.InitConfig)
cobra.OnInitialize(Config.InitConfig, ReBindKeys)

rootCmd.PersistentFlags().StringVar(&Config.Profile.APIKey, "api-key", "", "Your API key to use for the command")
rootCmd.PersistentFlags().StringVar(&Config.Color, "color", "", "turn on/off color output (on, off, auto)")
Expand All @@ -148,8 +172,13 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&Config.Profile.ProfileName, "project-name", "p", "default", "the project name to read from for config")
rootCmd.Flags().BoolP("version", "v", false, "Get the version of the Stripe CLI")

// tell viper to monitor the following flags:
// they will be available via viper.get(KEY), but not mapped back to the Config (by default; see below)
viper.BindPFlag("color", rootCmd.PersistentFlags().Lookup("color"))

// also, bind flags to the environment variables
bindEnv("project-name", "STRIPE_PROJECT_NAME")

rootCmd.AddCommand(newCompletionCmd().cmd)
rootCmd.AddCommand(newConfigCmd().cmd)
rootCmd.AddCommand(newDaemonCmd(&Config).cmd)
Expand Down
30 changes: 30 additions & 0 deletions pkg/cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"bytes"
"context"
"os"
"path/filepath"
"testing"

Expand Down Expand Up @@ -69,3 +70,32 @@ func TestExampleCommands(t *testing.T) {
require.Equal(t, err.Error(), "`stripe samples create` accepts at maximum 2 positional arguments. See `stripe samples create --help` for supported flags and usage")
}
}

func TestReadProjectDefault(t *testing.T) {
executeCommand(rootCmd, "version")
require.Equal(t, Config.Profile.ProfileName, "default")
}

func TestReadProjectFromEnv(t *testing.T) {
os.Setenv("STRIPE_PROJECT_NAME", "from-env")
defer os.Unsetenv("STRIPE_PROJECT_NAME")

executeCommand(rootCmd, "version")

require.Equal(t, Config.Profile.ProfileName, "from-env")
}

func TestReadProjectFromFlag(t *testing.T) {
executeCommand(rootCmd, "version", "--project-name", "from-flag")

require.Equal(t, Config.Profile.ProfileName, "from-flag")
}

func TestReadProjectFlagHasPrecedence(t *testing.T) {
os.Setenv("STRIPE_PROJECT_NAME", "from-env")
defer os.Unsetenv("STRIPE_PROJECT_NAME")

executeCommand(rootCmd, "version", "--project-name", "from-flag")

require.Equal(t, Config.Profile.ProfileName, "from-flag")
}
8 changes: 5 additions & 3 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,18 +203,20 @@ func (c *Config) EditConfig() error {

// PrintConfig outputs the contents of the configuration file.
func (c *Config) PrintConfig() error {
if c.Profile.ProfileName == "default" {
profileName := c.Profile.ProfileName

if profileName == "default" {
configFile, err := os.ReadFile(c.ProfilesFile)
if err != nil {
return err
}

fmt.Print(string(configFile))
} else {
configs := viper.GetStringMapString(c.Profile.ProfileName)
configs := viper.GetStringMapString(profileName)

if len(configs) > 0 {
fmt.Printf("[%s]\n", c.Profile.ProfileName)
fmt.Printf("[%s]\n", profileName)
for field, value := range configs {
fmt.Printf(" %s=%s\n", field, value)
}
Expand Down

0 comments on commit 7e58ee7

Please sign in to comment.