Skip to content

Commit

Permalink
Feature: Adds build variables to deployBranchCmd (#325)
Browse files Browse the repository at this point in the history
* Adds build variables to deployBranchCmd

* fixes gomod

* Adds tests and changes split logic for build env arguments

---------

Co-authored-by: Blaize Kaye <blaize.kaye@amazee.io>
  • Loading branch information
bomoko and Blaize Kaye authored Mar 19, 2024
1 parent af8dcdf commit a2838f8
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 11 deletions.
20 changes: 15 additions & 5 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
24 changes: 24 additions & 0 deletions cmd/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
94 changes: 94 additions & 0 deletions cmd/helpers_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"github.com/uselagoon/lagoon-cli/internal/schema"
"reflect"
"testing"

Expand Down Expand Up @@ -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)
}
})
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ mutation (
$project: String!,
$branch: String!,
$branchRef: String,
$returnData: Boolean!) {
$returnData: Boolean!,
$buildVariables: [EnvKeyValueInput]) {
deployEnvironmentBranch(input: {
project:{
name: $project
}
branchName: $branch
branchRef: $branchRef
returnData: $returnData
buildVariables: $buildVariables
}
)
}
9 changes: 5 additions & 4 deletions internal/schema/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions internal/schema/envVar.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}

0 comments on commit a2838f8

Please sign in to comment.