From 337ed1fc46c47da8dbd77501d1dcbf02b510efa2 Mon Sep 17 00:00:00 2001 From: jon4hz Date: Fri, 24 Feb 2023 23:20:30 +0100 Subject: [PATCH 1/2] fix: properly support default environment --- cli/packages/cmd/export.go | 2 +- cli/packages/cmd/run.go | 2 +- cli/packages/cmd/secrets.go | 10 +- cli/packages/util/helper.go | 14 ++- cli/packages/util/secrets.go | 24 +++-- cli/packages/util/secrets_test.go | 98 +++++++++++++++++++ .../util/testdata/infisical-branch-env.json | 7 ++ .../util/testdata/infisical-default-env.json | 5 + .../infisical-no-matching-branch-env.json | 7 ++ 9 files changed, 153 insertions(+), 16 deletions(-) create mode 100644 cli/packages/util/testdata/infisical-branch-env.json create mode 100644 cli/packages/util/testdata/infisical-default-env.json create mode 100644 cli/packages/util/testdata/infisical-no-matching-branch-env.json diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 649de41f2..d99686aeb 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -38,7 +38,7 @@ var exportCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { - environmentFromWorkspace := util.GetEnvelopmentBasedOnGitBranch() + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() if environmentFromWorkspace != "" { environmentName = environmentFromWorkspace } diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index f70d29726..c04a12d58 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -56,7 +56,7 @@ var runCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { - environmentFromWorkspace := util.GetEnvelopmentBasedOnGitBranch() + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() if environmentFromWorkspace != "" { environmentName = environmentFromWorkspace } diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 625152aa9..b6805ed50 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -32,7 +32,7 @@ var secretsCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { - environmentFromWorkspace := util.GetEnvelopmentBasedOnGitBranch() + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() if environmentFromWorkspace != "" { environmentName = environmentFromWorkspace } @@ -98,7 +98,7 @@ var secretsSetCmd = &cobra.Command{ environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { - environmentFromWorkspace := util.GetEnvelopmentBasedOnGitBranch() + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() if environmentFromWorkspace != "" { environmentName = environmentFromWorkspace } @@ -277,7 +277,7 @@ var secretsDeleteCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { - environmentFromWorkspace := util.GetEnvelopmentBasedOnGitBranch() + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() if environmentFromWorkspace != "" { environmentName = environmentFromWorkspace } @@ -338,7 +338,7 @@ var secretsDeleteCmd = &cobra.Command{ func getSecretsByNames(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { - environmentFromWorkspace := util.GetEnvelopmentBasedOnGitBranch() + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() if environmentFromWorkspace != "" { environmentName = environmentFromWorkspace } @@ -384,7 +384,7 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { func generateExampleEnv(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { - environmentFromWorkspace := util.GetEnvelopmentBasedOnGitBranch() + environmentFromWorkspace := util.GetEnvFromWorkspaceFile() if environmentFromWorkspace != "" { environmentName = environmentFromWorkspace } diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 8d70e9e0a..59f245fc1 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -115,8 +115,20 @@ func GetHashFromStringList(list []string) string { return fmt.Sprintf("%x", sum) } +// execCmd is a struct that holds the command and arguments to be executed. +// By using this struct, we can easily mock the command and arguments. +type execCmd struct { + cmd string + args []string +} + +var getCurrentBranchCmd = execCmd{ + cmd: "git", + args: []string{"symbolic-ref", "--short", "HEAD"}, +} + func getCurrentBranch() (string, error) { - cmd := exec.Command("git", "symbolic-ref", "--short", "HEAD") + cmd := exec.Command(getCurrentBranchCmd.cmd, getCurrentBranchCmd.args...) var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index 95065de66..5d78e65e2 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -482,21 +482,29 @@ func DeleteBackupSecrets() error { return os.RemoveAll(fullPathToSecretsBackupFolder) } -func GetEnvelopmentBasedOnGitBranch() string { +func GetEnvFromWorkspaceFile() string { + workspaceFile, err := GetWorkSpaceFromFile() + if err != nil { + log.Debugf("getEnvFromWorkspaceFile: [err=%s]", err) + return "" + } + + if env := GetEnvelopmentBasedOnGitBranch(workspaceFile); env != "" { + return env + } + + return workspaceFile.DefaultEnvironment +} + +func GetEnvelopmentBasedOnGitBranch(workspaceFile models.WorkspaceConfigFile) string { branch, err := getCurrentBranch() if err != nil { log.Debugf("getEnvelopmentBasedOnGitBranch: [err=%s]", err) } - workspaceFile, err := GetWorkSpaceFromFile() - if err != nil { - log.Debugf("getEnvelopmentBasedOnGitBranch: [err=%s]", err) - return "" - } - envBasedOnGitBranch, ok := workspaceFile.GitBranchToEnvironmentMapping[branch] - log.Debugf("GetEnvelopmentBasedOnGitBranch: [envBasedOnGitBranch=%s] [ok=%s]", envBasedOnGitBranch, ok) + log.Debugf("GetEnvelopmentBasedOnGitBranch: [envBasedOnGitBranch=%s] [ok=%t]", envBasedOnGitBranch, ok) if err == nil && ok { return envBasedOnGitBranch diff --git a/cli/packages/util/secrets_test.go b/cli/packages/util/secrets_test.go index 513e4f7e3..c63b96be9 100644 --- a/cli/packages/util/secrets_test.go +++ b/cli/packages/util/secrets_test.go @@ -1,6 +1,9 @@ package util import ( + "io" + "os" + "path" "testing" "github.com/Infisical/infisical-merge/packages/models" @@ -158,3 +161,98 @@ func Test_SubstituteSecrets_When_No_SubstituteNeeded(t *testing.T) { } } } + +func Test_Read_Env_From_File(t *testing.T) { + type testCase struct { + TestFile string + ExpectedEnv string + } + + var cases = []testCase{ + { + TestFile: "testdata/infisical-default-env.json", + ExpectedEnv: "myDefaultEnv", + }, + { + TestFile: "testdata/infisical-branch-env.json", + ExpectedEnv: "myMainEnv", + }, + { + TestFile: "testdata/infisical-no-matching-branch-env.json", + ExpectedEnv: "myDefaultEnv", + }, + } + + // create a tmp directory for testing + testDir, err := os.MkdirTemp(os.TempDir(), "infisical-test") + if err != nil { + t.Errorf("Test_Read_DefaultEnv_From_File: Failed to create temp directory: %s", err) + } + + // safe the current working directory + originalDir, err := os.Getwd() + if err != nil { + t.Errorf("Test_Read_DefaultEnv_From_File: Failed to get current working directory: %s", err) + } + + // backup the original git command + originalGitCmd := getCurrentBranchCmd + + // make sure to clean up after the test + t.Cleanup(func() { + os.Chdir(originalDir) + os.RemoveAll(testDir) + getCurrentBranchCmd = originalGitCmd + }) + + // mock the git command to return "main" as the current branch + getCurrentBranchCmd = execCmd{cmd: "echo", args: []string{"main"}} + + for _, c := range cases { + // make sure we start in the original directory + err = os.Chdir(originalDir) + if err != nil { + t.Errorf("Test_Read_DefaultEnv_From_File: Failed to change working directory: %s", err) + } + + // remove old test file if it exists + err = os.Remove(path.Join(testDir, INFISICAL_WORKSPACE_CONFIG_FILE_NAME)) + if err != nil && !os.IsNotExist(err) { + t.Errorf("Test_Read_DefaultEnv_From_File: Failed to remove old test file: %s", err) + } + + // deploy the test file + copyTestFile(t, c.TestFile, path.Join(testDir, INFISICAL_WORKSPACE_CONFIG_FILE_NAME)) + + // change the working directory to the tmp directory + err = os.Chdir(testDir) + if err != nil { + t.Errorf("Test_Read_DefaultEnv_From_File: Failed to change working directory: %s", err) + } + + // get env from file + env := GetEnvFromWorkspaceFile() + if env != c.ExpectedEnv { + t.Errorf("Test_Read_DefaultEnv_From_File: Expected env to be %s but got %s", c.ExpectedEnv, env) + } + } +} + +func copyTestFile(t *testing.T, src, dst string) { + srcFile, err := os.Open(src) + if err != nil { + t.Errorf("Test_Read_Env_From_File_By_Branch: Failed to open source file: %s", err) + } + defer srcFile.Close() + + dstFile, err := os.Create(dst) + if err != nil { + t.Errorf("Test_Read_Env_From_File_By_Branch: Failed to create destination file: %s", err) + } + defer dstFile.Close() + + _, err = io.Copy(dstFile, srcFile) + if err != nil { + t.Errorf("Test_Read_Env_From_File_By_Branch: Failed to copy file: %s", err) + } +} diff --git a/cli/packages/util/testdata/infisical-branch-env.json b/cli/packages/util/testdata/infisical-branch-env.json new file mode 100644 index 000000000..657d68cd9 --- /dev/null +++ b/cli/packages/util/testdata/infisical-branch-env.json @@ -0,0 +1,7 @@ +{ + "workspaceId": "12345678", + "defaultEnvironment": "myDefaultEnv", + "gitBranchToEnvironmentMapping": { + "main": "myMainEnv" + } +} \ No newline at end of file diff --git a/cli/packages/util/testdata/infisical-default-env.json b/cli/packages/util/testdata/infisical-default-env.json new file mode 100644 index 000000000..63d37ad87 --- /dev/null +++ b/cli/packages/util/testdata/infisical-default-env.json @@ -0,0 +1,5 @@ +{ + "workspaceId": "12345678", + "defaultEnvironment": "myDefaultEnv", + "gitBranchToEnvironmentMapping": null +} \ No newline at end of file diff --git a/cli/packages/util/testdata/infisical-no-matching-branch-env.json b/cli/packages/util/testdata/infisical-no-matching-branch-env.json new file mode 100644 index 000000000..101dc61d6 --- /dev/null +++ b/cli/packages/util/testdata/infisical-no-matching-branch-env.json @@ -0,0 +1,7 @@ +{ + "workspaceId": "12345678", + "defaultEnvironment": "myDefaultEnv", + "gitBranchToEnvironmentMapping": { + "notmain": "myMainEnv" + } +} \ No newline at end of file From 8f974fb0874fcf4c93571cb22e62f6b42bad8e9c Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Sat, 25 Feb 2023 13:07:07 -0500 Subject: [PATCH 2/2] Add docs for default environment --- docs/cli/project-config.mdx | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/cli/project-config.mdx b/docs/cli/project-config.mdx index 26ccc743d..5c125ff88 100644 --- a/docs/cli/project-config.mdx +++ b/docs/cli/project-config.mdx @@ -7,6 +7,24 @@ To link your local project on your machine with an Infisical project, we suggest The `.infisical.json` file specifies various parameters, such as the Infisical project to retrieve secrets from, along with other configuration options. Furthermore, you can define additional properties in the file to further tailor your local development experience. +## Set default environment +If you need to change environments while using the CLI, you can do so by including the `--env` flag in your command. +However, this can be inconvenient if you typically work in just one environment. +To simplify the process, you can establish a default environment, which will be used for every command unless you specify otherwise. + +```json .infisical.json +{ + "workspaceId": "63ee5410a45f7a1ed39ba118", + "defaultEnvironment": "test", + "gitBranchToEnvironmentMapping": null +} +``` + +### How it works +If both `defaultEnvironment` and `gitBranchToEnvironmentMapping` are configured, `gitBranchToEnvironmentMapping` will take precedence over `defaultEnvironment`. +However, if `gitBranchToEnvironmentMapping` is not set and `defaultEnvironment` is, then the `defaultEnvironment` will be used to execute your Infisical CLI commands. +If you wish to override the `defaultEnvironment`, you can do so by using the `--env` flag explicitly. + ## Set Infisical environment based on GitHub branch When fetching your secrets from Infisical, you can switch between environments by using the `--env` flag. However, in certain cases, you may prefer the environment to be automatically mapped based on the current GitHub branch you are working on. To achieve this, simply add the `gitBranchToEnvironmentMapping` property to your configuration file, as shown below. @@ -23,4 +41,4 @@ To achieve this, simply add the `gitBranchToEnvironmentMapping` property to your ### How it works After configuring this property, every time you use the CLI with the specified configuration file, it will automatically verify if there is a corresponding environment mapping for the current Github branch you are on. -If it exists, the CLI will use that environment to retrieve secrets. You can override this behavior by explicitly using the `--env` flag while interacting with the CLI. \ No newline at end of file +If it exists, the CLI will use that environment to retrieve secrets. You can override this behavior by explicitly using the `--env` flag while interacting with the CLI.