-
Notifications
You must be signed in to change notification settings - Fork 42
/
parameters.go
143 lines (117 loc) · 3.38 KB
/
parameters.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package client
import (
"fmt"
"strings"
"github.com/innogames/slack-bot/v2/bot/util"
"github.com/innogames/slack-bot/v2/bot/config"
"github.com/innogames/slack-bot/v2/client/vcs"
)
// Parameters is a simple string map of all build parameters
type Parameters map[string]string
func (p Parameters) String() string {
out := ""
for key, value := range p {
if key == slackUserParameter || key == util.FullMatch {
continue
}
out += key + ": '" + value + "' "
}
if out == "" {
return "-none-"
}
return strings.TrimSpace(out)
}
// ParameterModifier are functions to mutate given Jenkins parameters
// e.g. ensure the parameter is a real "boolean" value
type ParameterModifier func(string) (string, error)
var parameterModifier = map[string]ParameterModifier{
"branch": vcs.GetMatchingBranch,
"lowerCase": func(input string) (string, error) {
return strings.ToLower(input), nil
},
"upperCase": func(input string) (string, error) {
return strings.ToUpper(input), nil
},
"bool": func(value string) (string, error) {
switch value {
case "false", "FALSE", "0", "null", "", " ":
return "false", nil
default:
return "true", nil
}
},
}
// if a job was triggered via bot we send this additional build param to jenkins with the slack user name
const slackUserParameter = "SLACK_USER"
// ParseParameters parse jenkins parameters, based on a input string
func ParseParameters(jobConfig config.JobConfig, parameterString string, params Parameters) error {
givenParameters := parseWords(parameterString)
var err error
for index, parameterConfig := range jobConfig.Parameters {
var value string
if len(givenParameters) > index {
// parameterName given in string
value = givenParameters[index]
} else if paramValue, ok := params[parameterConfig.Name]; ok && paramValue != "" {
// use given names parameterName!
value = params[parameterConfig.Name]
} else if parameterConfig.Default != "" {
// use default value
value = parameterConfig.Default
} else {
err := fmt.Errorf("sorry, you have to pass %d parameters (%s)", len(jobConfig.Parameters), strings.Join(getNames(jobConfig.Parameters), ", "))
return err
}
if modifier, ok := parameterModifier[parameterConfig.Type]; ok {
value, err = modifier(value)
if err != nil {
return err
}
}
params[parameterConfig.Name] = value
}
return nil
}
// todo cleanup, is there a nice tokenizer in place somewhere?
// 'test "foo bar" 12' -> ["test", "foo bar" "12"]
func parseWords(parameterString string) []string {
parameters := make([]string, 0)
cur := strings.TrimSpace(parameterString)
var c byte
param := make([]byte, 0)
isQuoted := false
for len(cur) > 0 {
c, cur = cur[0], cur[1:]
switch {
case c == '"':
if isQuoted {
isQuoted = false
parameters = append(parameters, string(param))
param = make([]byte, 0)
} else {
isQuoted = true
}
case c == ' ' && !isQuoted:
// next param
if len(param) > 0 {
parameters = append(parameters, string(param))
}
param = make([]byte, 0)
default:
// append char to current param
param = append(param, c)
}
}
if len(param) > 0 {
// open quoting...just add it as last parameter
parameters = append(parameters, string(param))
}
return parameters
}
func getNames(list []config.JobParameter) []string {
keys := make([]string, len(list))
for i, parameter := range list {
keys[i] = parameter.Name
}
return keys
}