• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / workflows / 1354855011

01 Jul 2024 12:34AM UTC coverage: 81.632% (-0.3%) from 81.882%
1354855011

Pull #327

gitlab-ci

web-flow
chore: bump golang in the docker-dependencies group

Bumps the docker-dependencies group with 1 update: golang.


Updates `golang` from 1.22.3-alpine3.19 to 1.22.4-alpine3.19

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docker-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #327: chore: bump golang from 1.22.3-alpine3.19 to 1.22.4-alpine3.19 in the docker-dependencies group

1631 of 1998 relevant lines covered (81.63%)

14.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.47
/app/processor/string.go
1
// Copyright 2022 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
package processor
16

17
import (
18
        "bytes"
19
        "html"
20
        "net/url"
21
        "os"
22
        "regexp"
23
        "strings"
24
        "text/template"
25

26
        "github.com/thedevsaddam/gojsonq"
27

28
        "github.com/mendersoftware/workflows/model"
29
        "github.com/mendersoftware/workflows/utils"
30
)
31

32
const (
33
        workflowEnvVariable   = "env."
34
        workflowInputVariable = "workflow.input."
35
        regexVariable         = `\$\{(?P<options>(?:(?:[a-zA-Z]+)=(?:[a-zA-Z0-9]+);)*)` +
36
                `(?P<name>[^;\}\|]+)(?:\|(?P<default>[^\}]+))?}`
37
        regexOutputVariable = `(.*)\.json\.(.*)`
38

39
        encodingFlag = "encoding"
40
        encodingURL  = "url"
41
        encodingHTML = "html"
42
)
43

44
var (
45
        reExpression       = regexp.MustCompile(regexVariable)
46
        reExpressionOutput = regexp.MustCompile(regexOutputVariable)
47

48
        reMatchIndexOptions = reExpression.SubexpIndex("options")
49
        reMatchIndexName    = reExpression.SubexpIndex("name")
50
        reMatchIndexDefault = reExpression.SubexpIndex("default")
51
)
52

53
type Encoding int64
54

55
const (
56
        EncodingPlain Encoding = iota
57
        EncodingURL
58
        EncodingHTML
59
)
60

61
func ParseString(s string) Encoding {
×
62
        var enc Encoding
×
63
        switch s {
×
64
        case encodingURL:
×
65
                enc = EncodingURL
×
66
        case encodingHTML:
×
67
                enc = EncodingHTML
×
68
        default:
×
69
                enc = EncodingPlain
×
70
        }
71
        return enc
×
72
}
73

74
func (enc Encoding) Apply(s string) string {
134✔
75
        switch enc {
134✔
76
        case EncodingURL:
59✔
77
                return url.QueryEscape(s)
59✔
78
        case EncodingHTML:
1✔
79
                return html.EscapeString(s)
1✔
80
        }
81
        return s
74✔
82
}
83

84
type JobStringProcessor struct {
85
        workflow *model.Workflow
86
        job      *model.Job
87
}
88

89
type Options struct {
90
        Encoding Encoding
91
}
92

93
func NewJobStringProcessor(
94
        workflow *model.Workflow,
95
        job *model.Job,
96
) *JobStringProcessor {
34✔
97
        return &JobStringProcessor{
34✔
98
                workflow: workflow,
34✔
99
                job:      job,
34✔
100
        }
34✔
101
}
34✔
102

103
func processOptionString(expression string) (opts Options) {
138✔
104
        const (
138✔
105
                flagTokenCount = 2
138✔
106
                lValueIndex    = 0
138✔
107
                rValueIndex    = 1
138✔
108
        )
138✔
109
        for _, flagToken := range strings.Split(expression, ";") {
344✔
110
                flagValueTokens := strings.SplitN(flagToken, "=", 2)
206✔
111
                if len(flagValueTokens) < flagTokenCount {
344✔
112
                        continue
138✔
113
                }
114
                if flagValueTokens[lValueIndex] == encodingFlag {
132✔
115
                        switch flagValueTokens[rValueIndex] {
64✔
116
                        case encodingURL:
62✔
117
                                opts.Encoding = EncodingURL
62✔
118
                        case encodingHTML:
×
119
                                opts.Encoding = EncodingHTML
×
120
                        }
121
                }
122
        }
123
        return
138✔
124
}
125

126
func (j *JobStringProcessor) ProcessJobString(data string) string {
127✔
127
        matches := reExpression.FindAllStringSubmatch(data, -1)
127✔
128

127✔
129
        // search for ${...} expressions in the data string
127✔
130
SubMatchLoop:
127✔
131
        for _, submatch := range matches {
260✔
132
                // content of the ${...} expression, without the brackets
133✔
133
                varName := submatch[reMatchIndexName]
133✔
134
                value := submatch[reMatchIndexDefault]
133✔
135
                options := processOptionString(submatch[reMatchIndexOptions])
133✔
136
                // now it is possible to override the encoding with flags: ${encoding=plain;identifier}
133✔
137
                // if encoding is supplied via flags, it takes precedence, we return the match
133✔
138
                // without the flags, otherwise fail back to original match and encoding
133✔
139
                if strings.HasPrefix(varName, workflowInputVariable) &&
133✔
140
                        len(varName) > len(workflowInputVariable) {
226✔
141
                        // Replace ${workflow.input.KEY} with the KEY input variable
93✔
142
                        paramName := varName[len(workflowInputVariable):]
93✔
143
                        for _, param := range j.job.InputParameters {
318✔
144
                                if param.Name == paramName {
318✔
145
                                        value = param.Value
93✔
146
                                        break
93✔
147
                                }
148
                        }
149
                } else if strings.HasPrefix(varName, workflowEnvVariable) &&
40✔
150
                        len(varName) > len(workflowEnvVariable) {
80✔
151
                        // Replace ${env.KEY} with the KEY environment variable
40✔
152
                        envName := varName[len(workflowEnvVariable):]
40✔
153
                        if envValue := os.Getenv(envName); envValue != "" {
48✔
154
                                value = envValue
8✔
155
                        }
8✔
156
                } else if output := reExpressionOutput.FindStringSubmatch(varName); len(output) > 0 {
×
157
                        // Replace ${TASK_NAME.json.JSONPATH} with the value of the JSONPATH expression from the
×
158
                        // JSON output of the previous task with name TASK_NAME. If the output is not a valid
×
159
                        // JSON or the JSONPATH does not resolve to a value, replace with empty string
×
160
                        for _, result := range j.job.Results {
×
161
                                if result.Name == output[1] {
×
162
                                        varKey := output[2]
×
163
                                        var output string
×
164
                                        if result.Type == model.TaskTypeHTTP {
×
165
                                                output = result.HTTPResponse.Body
×
166
                                        } else if result.Type == model.TaskTypeCLI {
×
167
                                                output = result.CLI.Output
×
168
                                        } else {
×
169
                                                continue
×
170
                                        }
171
                                        varValue := gojsonq.New().FromString(output).Find(varKey)
×
172
                                        if varValue == nil {
×
173
                                                varValue = ""
×
174
                                        }
×
175
                                        varValueString, err := utils.ConvertAnythingToString(varValue)
×
176
                                        if err == nil {
×
177
                                                if varValueString != "" {
×
178
                                                        value = varValueString
×
179
                                                }
×
180
                                        } else {
×
181
                                                continue SubMatchLoop
×
182
                                        }
183
                                        break
×
184
                                }
185
                        }
186
                }
187
                value = options.Encoding.Apply(value)
133✔
188
                data = strings.ReplaceAll(data, submatch[0], value)
133✔
189
        }
190

191
        return data
127✔
192
}
193

194
// MaybeExecuteGoTemplate tries to parse and execute data as a go template
195
// if it fails to do so, data is returned.
196
func (j *JobStringProcessor) MaybeExecuteGoTemplate(data string) string {
29✔
197
        input := j.job.InputParameters.Map()
29✔
198
        tmpl, err := template.New("go-template").Parse(data)
29✔
199
        if err != nil {
29✔
200
                return data
×
201
        }
×
202
        buf := &bytes.Buffer{}
29✔
203
        err = tmpl.Execute(buf, input)
29✔
204
        if err != nil {
29✔
205
                return data
×
206
        }
×
207
        return buf.String()
29✔
208
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc