Skip to content

Commit

Permalink
pipeline variables - set and delete variables, but doesn't support
Browse files Browse the repository at this point in the history
commas or equal symbols...
  • Loading branch information
3ximus committed Feb 19, 2024
1 parent 12a7787 commit b198b2a
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 27 deletions.
73 changes: 57 additions & 16 deletions api/bb-api.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,22 +416,6 @@ func GetPipelineStepLogs(repository string, id string, stepId string, offset int
return channel
}

func GetPipelineVariables(repository string) <-chan EnvironmentVariable {
channel := make(chan EnvironmentVariable)
go func() {
defer close(channel)

var environmentResponse BBPaginatedResponse[EnvironmentVariable]
response := bbApiGet(fmt.Sprintf("repositories/%s/pipelines_config/variables", repository))
err := json.Unmarshal(response, &environmentResponse)
cobra.CheckErr(err)
for _, envVar := range environmentResponse.Values {
channel <- envVar
}
}()
return channel
}

func GetPipelineReport(repository string, id string, stepId string) <-chan PipelineReport {
channel := make(chan PipelineReport)
go func() {
Expand Down Expand Up @@ -476,6 +460,63 @@ func StopPipeline(repository string, id string) {
bbApiPost(fmt.Sprintf("repositories/%s/pipelines/%s/stopPipeline", repository, id), nil)
}

func GetPipelineVariables(repository string) <-chan []EnvironmentVariable {
channel := make(chan []EnvironmentVariable)
go func() {
defer close(channel)
var environmentResponse BBPaginatedResponse[EnvironmentVariable]
response := bbApiGet(fmt.Sprintf("repositories/%s/pipelines_config/variables?pagelen=200", repository))
err := json.Unmarshal(response, &environmentResponse)
cobra.CheckErr(err)
channel <- environmentResponse.Values
}()
return channel
}

func CreatePipelineVariable(repository string, key string, value string) <-chan EnvironmentVariable {
channel := make(chan EnvironmentVariable)
go func() {
defer close(channel)
body := EnvironmentVariable{
Key: key,
Value: value,
Secured: false,
}
content, err := json.Marshal(body)
cobra.CheckErr(err)
response := bbApiPost(fmt.Sprintf("repositories/%s/pipelines_config/variables", repository), bytes.NewReader(content))
var newVar EnvironmentVariable
err = json.Unmarshal(response, &newVar)
cobra.CheckErr(err)
channel <- newVar
}()
return channel
}

func UpdatePipelineVariable(repository string, varUUID string, key string, value string) <-chan EnvironmentVariable {
channel := make(chan EnvironmentVariable)
go func() {
defer close(channel)
body := EnvironmentVariable{
Key: key,
Value: value,
Secured: false,
}
content, err := json.Marshal(body)
cobra.CheckErr(err)
response := bbApiPut(fmt.Sprintf("repositories/%s/pipelines_config/variables/%s", repository, varUUID), bytes.NewReader(content))
var newVar EnvironmentVariable
err = json.Unmarshal(response, &newVar)
cobra.CheckErr(err)
channel <- newVar
}()
return channel
}

func DeletePipelineVariable(repository string, varUUID string) {
bbApiDelete(fmt.Sprintf("repositories/%s/pipelines_config/variables/%s", repository, varUUID))
}

func GetEnvironmentList(repository string, status bool) <-chan Environment {
channel := make(chan Environment)
go func() {
Expand Down
7 changes: 4 additions & 3 deletions api/bb-types.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,10 @@ type Environment struct {
}

type EnvironmentVariable struct {
Key string
Value string
Secured bool
UUID string
Key string `json:"key"`
Value string `json:"value"`
Secured bool `json:"secured"`
}

// DEFAULT ACTIONS OVERRIDES
Expand Down
70 changes: 62 additions & 8 deletions cmd/pipeline/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,79 @@ package pipeline

import (
"bb/api"
"bb/util"
"fmt"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var VariablesCmd = &cobra.Command{
Use: "variables",
Short: "List pipeline variables",
Long: "List pipeline variables. If variable is secured only *** is displayed",
Short: "Manage pipeline variables",
Long: "Manage pipeline variables. If variable is secured only *** is displayed",
Aliases: []string{"var"},
Run: func(cmd *cobra.Command, args []string) {
for variable := range api.GetPipelineVariables(viper.GetString("repo")) {
if variable.Secured {
fmt.Printf("%s = \033[37m***\033[m", variable.Key)
} else {
fmt.Printf("%s = \033[37m%s\033[m", variable.Key, variable.Value)
repo := viper.GetString("repo")
variables := <-api.GetPipelineVariables(repo)

setVars, _ := cmd.Flags().GetStringSlice("set")
if len(setVars) > 0 {
for _, v := range setVars {
keyVal := strings.Split(v, "=")
if len(keyVal) != 2 {
cobra.CheckErr(fmt.Sprintf("Variable \"%s\" must be in the format \"KEY=VALUE\"", v))
}
updated := false
for _, ev := range variables {
if ev.Key == keyVal[0] {
updatedVar := <-api.UpdatePipelineVariable(repo, ev.UUID, keyVal[0], keyVal[1])
util.Printf("\033[1;34mUpdated\033[m \"%s=%s\"\n", updatedVar.Key, updatedVar.Value)
updated = true
break
}
}
if !updated {
createdVar := <-api.CreatePipelineVariable(repo, keyVal[0], keyVal[1])
util.Printf("\033[1;32mCreated\033[m \"%s=%s\"\n", createdVar.Key, createdVar.Value)
}
}
}

deleteVars, _ := cmd.Flags().GetStringSlice("delete")
if len(deleteVars) > 0 {
for _, toDelete := range deleteVars {
for _, ev := range variables {
if ev.Key == toDelete {
api.DeletePipelineVariable(repo, ev.UUID)
util.Printf("\033[1;31mDeleted\033[m \"%s\"\n", ev.Key)
break
}
}
}

}

if len(setVars) == 0 && len(deleteVars) == 0 {
for _, variable := range variables {
if variable.Secured {
util.Printf("%s = \033[37m***\033[m", variable.Key)
} else {
util.Printf("%s = \033[37m%s\033[m", variable.Key, variable.Value)
}
fmt.Println()
}
fmt.Println()
}
},
}

func init() {
// TODO make it possible to set secure variables with a special flag. Maybe A=B
// TODO Commas are used to separate variables within the same flag so "-s A=B,X" will not set variable A to the value B,X
// So we must not use StringSlice and use String array instead ?
// TODO It cannot also handle = signs
VariablesCmd.Flags().StringSliceP("set", "s", []string{}, `set one or multiple variables. If the variable doesn't exist one is created.
Variables must be in the format KEY=VALUE`)
VariablesCmd.Flags().StringSliceP("delete", "d", []string{}, "delete one or multiple variables")
}
14 changes: 14 additions & 0 deletions util/util.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// vim: foldmethod=indent foldnestmax=1

package util

import (
"bb/api"
"fmt"
"os"
"os/exec"
"regexp"
"runtime"
"strconv"
"strings"
Expand All @@ -13,6 +16,7 @@ import (
"github.com/ktr0731/go-fuzzyfinder"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/term"
)

type ResultSwitchConfig struct {
Expand Down Expand Up @@ -222,3 +226,13 @@ func UseExternalFZF[T any](list []T, prompt string, toString func(int) string) [
}
return result
}

/* fmt.Printf wrapper to remove ANSI colors if stdout is not a terminal */
func Printf(format string, a ...any) {
if term.IsTerminal(int(os.Stdout.Fd())) {
fmt.Printf(format, a...)
} else {
ansiColorRegex := regexp.MustCompile(`\x1b\[[0-9;]*m`)
fmt.Printf(ansiColorRegex.ReplaceAllString(format, ""), a...)
}
}

0 comments on commit b198b2a

Please sign in to comment.