diff --git a/cmd/deploy.go b/cmd/deploy.go index c58081c6..9a95ec8a 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -3,7 +3,6 @@ package cmd import ( "context" "fmt" - "github.com/spf13/cobra" "github.com/uselagoon/lagoon-cli/internal/lagoon" "github.com/uselagoon/lagoon-cli/internal/lagoon/client" @@ -46,6 +45,16 @@ use 'lagoon deploy latest' instead`, if cmdProjectName == "" || branch == "" { return fmt.Errorf("Missing arguments: Project name or branch name is not defined") } + + buildVarStrings, err := cmd.Flags().GetStringSlice("buildvar") + if err != nil { + return err + } + buildVarMap, err := buildVarsToMap(buildVarStrings) + if err != nil { + return err + } + if yesNo(fmt.Sprintf("You are attempting to deploy branch '%s' for project '%s', are you sure?", branch, cmdProjectName)) { current := lagoonCLIConfig.Current lc := client.New( @@ -55,9 +64,10 @@ use 'lagoon deploy latest' instead`, lagoonCLIVersion, debug) depBranch := &schema.DeployEnvironmentBranchInput{ - Branch: branch, - Project: cmdProjectName, - ReturnData: returnData, + Branch: branch, + Project: cmdProjectName, + ReturnData: returnData, + BuildVariables: buildVarMap, } if branchRef != "" { depBranch.BranchRef = branchRef @@ -266,7 +276,7 @@ func init() { deployBranchCmd.Flags().StringP("branch", "b", "", "Branch name to deploy") deployBranchCmd.Flags().StringP("branchRef", "r", "", "Branch ref to deploy") deployBranchCmd.Flags().Bool("returnData", false, returnDataUsageText) - + deployBranchCmd.Flags().StringSlice("buildvar", []string{}, "Adds one or more build variables to deployment, key and values separated by `=`: `--buildvar KEY1=VALUE1 [--buildvar KEY2=VALUE2]`") deployPromoteCmd.Flags().StringP("destination", "d", "", "Destination environment name to create") deployPromoteCmd.Flags().StringP("source", "s", "", "Source environment name to use as the base to deploy from") deployPromoteCmd.Flags().Bool("returnData", false, returnDataUsageText) diff --git a/cmd/helpers.go b/cmd/helpers.go index 7176566a..e2cd5b9c 100644 --- a/cmd/helpers.go +++ b/cmd/helpers.go @@ -2,12 +2,15 @@ package cmd import ( "crypto/sha1" + "errors" "fmt" "regexp" "strings" "github.com/guregu/null" "github.com/spf13/pflag" + + "github.com/uselagoon/lagoon-cli/internal/schema" ) // makeSafe ensures that any string is dns safe @@ -53,3 +56,24 @@ func flagStringNullValueOrNil(flags *pflag.FlagSet, flag string) (*null.String, // if not defined, return nil return nil, nil } + +// buildVarsToMap is used to convert incoming build variable arguments into a structure consumable by the graphQL call +func buildVarsToMap(slice []string) ([]schema.EnvKeyValueInput, error) { + result := []schema.EnvKeyValueInput{} + + for _, entry := range slice { + // Split the entry by "=" + parts := strings.SplitN(entry, "=", 2) + if len(parts) != 2 { + return []schema.EnvKeyValueInput{}, errors.New("Malformed build variable entry (expects `KEY=VALUE`) got: " + entry) + } + + // Trim spaces from key and value + key := strings.TrimSpace(parts[0]) + value := strings.TrimSpace(parts[1]) + + result = append(result, schema.EnvKeyValueInput{Name: key, Value: value}) + } + + return result, nil +} diff --git a/cmd/helpers_test.go b/cmd/helpers_test.go index 59524a25..53dab2a8 100644 --- a/cmd/helpers_test.go +++ b/cmd/helpers_test.go @@ -1,6 +1,7 @@ package cmd import ( + "github.com/uselagoon/lagoon-cli/internal/schema" "reflect" "testing" @@ -164,3 +165,96 @@ func Test_flagStringNullValueOrNil(t *testing.T) { }) } } + +func Test_buildVarsToMap(t *testing.T) { + type args struct { + slice []string + } + tests := []struct { + name string + args args + want []schema.EnvKeyValueInput + wantErr bool + }{ + { + name: "Empty case", + args: args{ + slice: []string{}, + }, + want: []schema.EnvKeyValueInput{}, + wantErr: false, + }, + { + name: "Valid simple case", + args: args{ + slice: []string{ + "KEY1=VAL1", + }, + }, + want: []schema.EnvKeyValueInput{ + { + Name: "KEY1", + Value: "VAL1", + }, + }, + wantErr: false, + }, + { + name: "Invalid Case - should fail", + args: args{ + slice: []string{ + "FAILKEY", + }, + }, + want: []schema.EnvKeyValueInput{}, + wantErr: true, + }, + { + name: "Valid case - multiple entries", + args: args{ + slice: []string{ + "KEY1=VAL1", + "KEY2=VAL2", + }, + }, + want: []schema.EnvKeyValueInput{ + { + Name: "KEY1", + Value: "VAL1", + }, + { + Name: "KEY2", + Value: "VAL2", + }, + }, + wantErr: false, + }, + { + name: "Valid complex parse case - multiple '=' in string", + args: args{ + slice: []string{ + "KEY1=VAL1==", + }, + }, + want: []schema.EnvKeyValueInput{ + { + Name: "KEY1", + Value: "VAL1==", + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := buildVarsToMap(tt.args.slice) + if (err != nil) != tt.wantErr { + t.Errorf("buildVarsToMap() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("buildVarsToMap() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/go.mod b/go.mod index 27ff3ee7..f9473643 100644 --- a/go.mod +++ b/go.mod @@ -40,4 +40,4 @@ require ( golang.org/x/term v0.15.0 // indirect ) -//replace github.com/uselagoon/machinery => ../machinery +// replace github.com/uselagoon/machinery => ../machinery diff --git a/internal/lagoon/client/_lgraphql/deployEnvironmentBranch.graphql b/internal/lagoon/client/_lgraphql/deployEnvironmentBranch.graphql index f6c27f14..c525929b 100644 --- a/internal/lagoon/client/_lgraphql/deployEnvironmentBranch.graphql +++ b/internal/lagoon/client/_lgraphql/deployEnvironmentBranch.graphql @@ -2,7 +2,8 @@ mutation ( $project: String!, $branch: String!, $branchRef: String, - $returnData: Boolean!) { + $returnData: Boolean!, + $buildVariables: [EnvKeyValueInput]) { deployEnvironmentBranch(input: { project:{ name: $project @@ -10,6 +11,7 @@ mutation ( branchName: $branch branchRef: $branchRef returnData: $returnData + buildVariables: $buildVariables } ) } \ No newline at end of file diff --git a/internal/schema/deploy.go b/internal/schema/deploy.go index 6a8ab67a..ebadee53 100644 --- a/internal/schema/deploy.go +++ b/internal/schema/deploy.go @@ -30,10 +30,11 @@ type DeployEnvironmentPullrequest struct { // DeployEnvironmentBranchInput is used as the input for deploying a branch. type DeployEnvironmentBranchInput struct { - Project string `json:"project"` - Branch string `json:"branch"` - BranchRef string `json:"branchRef"` - ReturnData bool `json:"returnData"` + Project string `json:"project"` + Branch string `json:"branch"` + BranchRef string `json:"branchRef"` + ReturnData bool `json:"returnData"` + BuildVariables []EnvKeyValueInput `json:"buildVariables,omitempty"` } // DeployEnvironmentBranch is the response. diff --git a/internal/schema/envVar.go b/internal/schema/envVar.go index eb48015a..abd14cc9 100644 --- a/internal/schema/envVar.go +++ b/internal/schema/envVar.go @@ -47,3 +47,9 @@ type UpdateEnvVarResponse struct { type DeleteEnvVarResponse struct { DeleteEnvVar string `json:"deleteEnvVariableByName,omitempty"` } + +// EnvKeyValueInput is based on the Lagoon API type. +type EnvKeyValueInput struct { + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` +}