Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b25bae0

Browse files
committedFeb 7, 2023
Fix use actions compatible globbing
1 parent d5fa2e7 commit b25bae0

File tree

4 files changed

+743
-35
lines changed

4 files changed

+743
-35
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package workflowpattern
5+
6+
import "fmt"
7+
8+
type TraceWriter interface {
9+
Info(string, ...interface{})
10+
}
11+
12+
type EmptyTraceWriter struct{}
13+
14+
func (*EmptyTraceWriter) Info(string, ...interface{}) {
15+
}
16+
17+
type StdOutTraceWriter struct{}
18+
19+
func (*StdOutTraceWriter) Info(format string, args ...interface{}) {
20+
fmt.Printf(format+"\n", args...)
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package workflowpattern
5+
6+
import (
7+
"fmt"
8+
"regexp"
9+
"strings"
10+
)
11+
12+
type WorkflowPattern struct {
13+
Pattern string
14+
Negative bool
15+
Regex *regexp.Regexp
16+
}
17+
18+
func CompilePattern(rawpattern string) (*WorkflowPattern, error) {
19+
negative := false
20+
pattern := rawpattern
21+
if strings.HasPrefix(rawpattern, "!") {
22+
negative = true
23+
pattern = rawpattern[1:]
24+
}
25+
rpattern, err := PatternToRegex(pattern)
26+
if err != nil {
27+
return nil, err
28+
}
29+
regex, err := regexp.Compile(rpattern)
30+
if err != nil {
31+
return nil, err
32+
}
33+
return &WorkflowPattern{
34+
Pattern: pattern,
35+
Negative: negative,
36+
Regex: regex,
37+
}, nil
38+
}
39+
40+
func PatternToRegex(pattern string) (string, error) {
41+
var rpattern strings.Builder
42+
rpattern.WriteString("^")
43+
pos := 0
44+
errors := map[int]string{}
45+
for pos < len(pattern) {
46+
switch pattern[pos] {
47+
case '*':
48+
if pos+1 < len(pattern) && pattern[pos+1] == '*' {
49+
if pos+2 < len(pattern) && pattern[pos+2] == '/' {
50+
rpattern.WriteString("(.+/)?")
51+
pos += 3
52+
} else {
53+
rpattern.WriteString(".*")
54+
pos += 2
55+
}
56+
} else {
57+
rpattern.WriteString("[^/]*")
58+
pos++
59+
}
60+
case '+', '?':
61+
if pos > 0 {
62+
rpattern.WriteByte(pattern[pos])
63+
} else {
64+
rpattern.WriteString(regexp.QuoteMeta(string([]byte{pattern[pos]})))
65+
}
66+
pos++
67+
case '[':
68+
rpattern.WriteByte(pattern[pos])
69+
pos++
70+
if pos < len(pattern) && pattern[pos] == ']' {
71+
errors[pos] = "Unexpected empty brackets '[]'"
72+
pos++
73+
break
74+
}
75+
validChar := func(a, b, test byte) bool {
76+
return test >= a && test <= b
77+
}
78+
startPos := pos
79+
for pos < len(pattern) && pattern[pos] != ']' {
80+
switch pattern[pos] {
81+
case '-':
82+
if pos <= startPos || pos+1 >= len(pattern) {
83+
errors[pos] = "Invalid range"
84+
pos++
85+
break
86+
}
87+
validRange := func(a, b byte) bool {
88+
return validChar(a, b, pattern[pos-1]) && validChar(a, b, pattern[pos+1]) && pattern[pos-1] <= pattern[pos+1]
89+
}
90+
if !validRange('A', 'z') && !validRange('0', '9') {
91+
errors[pos] = "Ranges can only include a-z, A-Z, A-z, and 0-9"
92+
pos++
93+
break
94+
}
95+
rpattern.WriteString(pattern[pos : pos+2])
96+
pos += 2
97+
default:
98+
if !validChar('A', 'z', pattern[pos]) && !validChar('0', '9', pattern[pos]) {
99+
errors[pos] = "Ranges can only include a-z, A-Z and 0-9"
100+
pos++
101+
break
102+
}
103+
rpattern.WriteString(regexp.QuoteMeta(string([]byte{pattern[pos]})))
104+
pos++
105+
}
106+
}
107+
if pos >= len(pattern) || pattern[pos] != ']' {
108+
errors[pos] = "Missing closing bracket ']' after '['"
109+
pos++
110+
}
111+
rpattern.WriteString("]")
112+
pos++
113+
case '\\':
114+
if pos+1 >= len(pattern) {
115+
errors[pos] = "Missing symbol after \\"
116+
pos++
117+
break
118+
}
119+
rpattern.WriteString(regexp.QuoteMeta(string([]byte{pattern[pos+1]})))
120+
pos += 2
121+
default:
122+
rpattern.WriteString(regexp.QuoteMeta(string([]byte{pattern[pos]})))
123+
pos++
124+
}
125+
}
126+
if len(errors) > 0 {
127+
var errorMessage strings.Builder
128+
for position, err := range errors {
129+
if errorMessage.Len() > 0 {
130+
errorMessage.WriteString(", ")
131+
}
132+
errorMessage.WriteString(fmt.Sprintf("Position: %d Error: %s", position, err))
133+
}
134+
return "", fmt.Errorf("invalid Pattern '%s': %s", pattern, errorMessage.String())
135+
}
136+
rpattern.WriteString("$")
137+
return rpattern.String(), nil
138+
}
139+
140+
func CompilePatterns(patterns ...string) ([]*WorkflowPattern, error) {
141+
ret := []*WorkflowPattern{}
142+
for _, pattern := range patterns {
143+
cp, err := CompilePattern(pattern)
144+
if err != nil {
145+
return nil, err
146+
}
147+
ret = append(ret, cp)
148+
}
149+
return ret, nil
150+
}
151+
152+
// returns true if the workflow should be skipped paths/branches
153+
func Skip(sequence []*WorkflowPattern, input []string, traceWriter TraceWriter) bool {
154+
if len(sequence) == 0 {
155+
return false
156+
}
157+
for _, file := range input {
158+
matched := false
159+
for _, item := range sequence {
160+
if item.Regex.MatchString(file) {
161+
pattern := item.Pattern
162+
if item.Negative {
163+
matched = false
164+
traceWriter.Info("%s excluded by pattern %s", file, pattern)
165+
} else {
166+
matched = true
167+
traceWriter.Info("%s included by pattern %s", file, pattern)
168+
}
169+
}
170+
}
171+
if matched {
172+
return false
173+
}
174+
}
175+
return true
176+
}
177+
178+
// returns true if the workflow should be skipped paths-ignore/branches-ignore
179+
func Filter(sequence []*WorkflowPattern, input []string, traceWriter TraceWriter) bool {
180+
if len(sequence) == 0 {
181+
return false
182+
}
183+
for _, file := range input {
184+
matched := false
185+
for _, item := range sequence {
186+
if item.Regex.MatchString(file) == !item.Negative {
187+
pattern := item.Pattern
188+
traceWriter.Info("%s ignored by pattern %s", file, pattern)
189+
matched = true
190+
break
191+
}
192+
}
193+
if !matched {
194+
return false
195+
}
196+
}
197+
return true
198+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,417 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package workflowpattern
5+
6+
import (
7+
"strings"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestMatchPattern(t *testing.T) {
14+
kases := []struct {
15+
inputs []string
16+
patterns []string
17+
skipResult bool
18+
filterResult bool
19+
}{
20+
{
21+
patterns: []string{"*"},
22+
inputs: []string{"path/with/slash"},
23+
skipResult: true,
24+
filterResult: false,
25+
},
26+
{
27+
patterns: []string{"path/a", "path/b", "path/c"},
28+
inputs: []string{"meta", "path/b", "otherfile"},
29+
skipResult: false,
30+
filterResult: false,
31+
},
32+
{
33+
patterns: []string{"path/a", "path/b", "path/c"},
34+
inputs: []string{"path/b"},
35+
skipResult: false,
36+
filterResult: true,
37+
},
38+
{
39+
patterns: []string{"path/a", "path/b", "path/c"},
40+
inputs: []string{"path/c", "path/b"},
41+
skipResult: false,
42+
filterResult: true,
43+
},
44+
{
45+
patterns: []string{"path/a", "path/b", "path/c"},
46+
inputs: []string{"path/c", "path/b", "path/a"},
47+
skipResult: false,
48+
filterResult: true,
49+
},
50+
{
51+
patterns: []string{"path/a", "path/b", "path/c"},
52+
inputs: []string{"path/c", "path/b", "path/d", "path/a"},
53+
skipResult: false,
54+
filterResult: false,
55+
},
56+
{
57+
patterns: []string{},
58+
inputs: []string{},
59+
skipResult: false,
60+
filterResult: false,
61+
},
62+
{
63+
patterns: []string{"\\!file"},
64+
inputs: []string{"!file"},
65+
skipResult: false,
66+
filterResult: true,
67+
},
68+
{
69+
patterns: []string{"escape\\\\backslash"},
70+
inputs: []string{"escape\\backslash"},
71+
skipResult: false,
72+
filterResult: true,
73+
},
74+
{
75+
patterns: []string{".yml"},
76+
inputs: []string{"fyml"},
77+
skipResult: true,
78+
filterResult: false,
79+
},
80+
// https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#patterns-to-match-branches-and-tags
81+
{
82+
patterns: []string{"feature/*"},
83+
inputs: []string{"feature/my-branch"},
84+
skipResult: false,
85+
filterResult: true,
86+
},
87+
{
88+
patterns: []string{"feature/*"},
89+
inputs: []string{"feature/your-branch"},
90+
skipResult: false,
91+
filterResult: true,
92+
},
93+
{
94+
patterns: []string{"feature/**"},
95+
inputs: []string{"feature/beta-a/my-branch"},
96+
skipResult: false,
97+
filterResult: true,
98+
},
99+
{
100+
patterns: []string{"feature/**"},
101+
inputs: []string{"feature/beta-a/my-branch"},
102+
skipResult: false,
103+
filterResult: true,
104+
},
105+
{
106+
patterns: []string{"feature/**"},
107+
inputs: []string{"feature/mona/the/octocat"},
108+
skipResult: false,
109+
filterResult: true,
110+
},
111+
{
112+
patterns: []string{"main", "releases/mona-the-octocat"},
113+
inputs: []string{"main"},
114+
skipResult: false,
115+
filterResult: true,
116+
},
117+
{
118+
patterns: []string{"main", "releases/mona-the-octocat"},
119+
inputs: []string{"releases/mona-the-octocat"},
120+
skipResult: false,
121+
filterResult: true,
122+
},
123+
{
124+
patterns: []string{"*"},
125+
inputs: []string{"main"},
126+
skipResult: false,
127+
filterResult: true,
128+
},
129+
{
130+
patterns: []string{"*"},
131+
inputs: []string{"releases"},
132+
skipResult: false,
133+
filterResult: true,
134+
},
135+
{
136+
patterns: []string{"**"},
137+
inputs: []string{"all/the/branches"},
138+
skipResult: false,
139+
filterResult: true,
140+
},
141+
{
142+
patterns: []string{"**"},
143+
inputs: []string{"every/tag"},
144+
skipResult: false,
145+
filterResult: true,
146+
},
147+
{
148+
patterns: []string{"*feature"},
149+
inputs: []string{"mona-feature"},
150+
skipResult: false,
151+
filterResult: true,
152+
},
153+
{
154+
patterns: []string{"*feature"},
155+
inputs: []string{"feature"},
156+
skipResult: false,
157+
filterResult: true,
158+
},
159+
{
160+
patterns: []string{"*feature"},
161+
inputs: []string{"ver-10-feature"},
162+
skipResult: false,
163+
filterResult: true,
164+
},
165+
{
166+
patterns: []string{"v2*"},
167+
inputs: []string{"v2"},
168+
skipResult: false,
169+
filterResult: true,
170+
},
171+
{
172+
patterns: []string{"v2*"},
173+
inputs: []string{"v2.0"},
174+
skipResult: false,
175+
filterResult: true,
176+
},
177+
{
178+
patterns: []string{"v2*"},
179+
inputs: []string{"v2.9"},
180+
skipResult: false,
181+
filterResult: true,
182+
},
183+
{
184+
patterns: []string{"v[12].[0-9]+.[0-9]+"},
185+
inputs: []string{"v1.10.1"},
186+
skipResult: false,
187+
filterResult: true,
188+
},
189+
{
190+
patterns: []string{"v[12].[0-9]+.[0-9]+"},
191+
inputs: []string{"v2.0.0"},
192+
skipResult: false,
193+
filterResult: true,
194+
},
195+
// https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#patterns-to-match-file-paths
196+
{
197+
patterns: []string{"*"},
198+
inputs: []string{"README.md"},
199+
skipResult: false,
200+
filterResult: true,
201+
},
202+
{
203+
patterns: []string{"*"},
204+
inputs: []string{"server.rb"},
205+
skipResult: false,
206+
filterResult: true,
207+
},
208+
{
209+
patterns: []string{"*.jsx?"},
210+
inputs: []string{"page.js"},
211+
skipResult: false,
212+
filterResult: true,
213+
},
214+
{
215+
patterns: []string{"*.jsx?"},
216+
inputs: []string{"page.jsx"},
217+
skipResult: false,
218+
filterResult: true,
219+
},
220+
{
221+
patterns: []string{"**"},
222+
inputs: []string{"all/the/files.md"},
223+
skipResult: false,
224+
filterResult: true,
225+
},
226+
{
227+
patterns: []string{"*.js"},
228+
inputs: []string{"app.js"},
229+
skipResult: false,
230+
filterResult: true,
231+
},
232+
{
233+
patterns: []string{"*.js"},
234+
inputs: []string{"index.js"},
235+
skipResult: false,
236+
filterResult: true,
237+
},
238+
{
239+
patterns: []string{"**.js"},
240+
inputs: []string{"index.js"},
241+
skipResult: false,
242+
filterResult: true,
243+
},
244+
{
245+
patterns: []string{"**.js"},
246+
inputs: []string{"js/index.js"},
247+
skipResult: false,
248+
filterResult: true,
249+
},
250+
{
251+
patterns: []string{"**.js"},
252+
inputs: []string{"src/js/app.js"},
253+
skipResult: false,
254+
filterResult: true,
255+
},
256+
{
257+
patterns: []string{"docs/*"},
258+
inputs: []string{"docs/README.md"},
259+
skipResult: false,
260+
filterResult: true,
261+
},
262+
{
263+
patterns: []string{"docs/*"},
264+
inputs: []string{"docs/file.txt"},
265+
skipResult: false,
266+
filterResult: true,
267+
},
268+
{
269+
patterns: []string{"docs/**"},
270+
inputs: []string{"docs/README.md"},
271+
skipResult: false,
272+
filterResult: true,
273+
},
274+
{
275+
patterns: []string{"docs/**"},
276+
inputs: []string{"docs/mona/octocat.txt"},
277+
skipResult: false,
278+
filterResult: true,
279+
},
280+
{
281+
patterns: []string{"docs/**/*.md"},
282+
inputs: []string{"docs/README.md"},
283+
skipResult: false,
284+
filterResult: true,
285+
},
286+
{
287+
patterns: []string{"docs/**/*.md"},
288+
inputs: []string{"docs/mona/hello-world.md"},
289+
skipResult: false,
290+
filterResult: true,
291+
},
292+
{
293+
patterns: []string{"docs/**/*.md"},
294+
inputs: []string{"docs/a/markdown/file.md"},
295+
skipResult: false,
296+
filterResult: true,
297+
},
298+
{
299+
patterns: []string{"**/docs/**"},
300+
inputs: []string{"docs/hello.md"},
301+
skipResult: false,
302+
filterResult: true,
303+
},
304+
{
305+
patterns: []string{"**/docs/**"},
306+
inputs: []string{"dir/docs/my-file.txt"},
307+
skipResult: false,
308+
filterResult: true,
309+
},
310+
{
311+
patterns: []string{"**/docs/**"},
312+
inputs: []string{"space/docs/plan/space.doc"},
313+
skipResult: false,
314+
filterResult: true,
315+
},
316+
{
317+
patterns: []string{"**/README.md"},
318+
inputs: []string{"README.md"},
319+
skipResult: false,
320+
filterResult: true,
321+
},
322+
{
323+
patterns: []string{"**/README.md"},
324+
inputs: []string{"js/README.md"},
325+
skipResult: false,
326+
filterResult: true,
327+
},
328+
{
329+
patterns: []string{"**/*src/**"},
330+
inputs: []string{"a/src/app.js"},
331+
skipResult: false,
332+
filterResult: true,
333+
},
334+
{
335+
patterns: []string{"**/*src/**"},
336+
inputs: []string{"my-src/code/js/app.js"},
337+
skipResult: false,
338+
filterResult: true,
339+
},
340+
{
341+
patterns: []string{"**/*-post.md"},
342+
inputs: []string{"my-post.md"},
343+
skipResult: false,
344+
filterResult: true,
345+
},
346+
{
347+
patterns: []string{"**/*-post.md"},
348+
inputs: []string{"path/their-post.md"},
349+
skipResult: false,
350+
filterResult: true,
351+
},
352+
{
353+
patterns: []string{"**/migrate-*.sql"},
354+
inputs: []string{"migrate-10909.sql"},
355+
skipResult: false,
356+
filterResult: true,
357+
},
358+
{
359+
patterns: []string{"**/migrate-*.sql"},
360+
inputs: []string{"db/migrate-v1.0.sql"},
361+
skipResult: false,
362+
filterResult: true,
363+
},
364+
{
365+
patterns: []string{"**/migrate-*.sql"},
366+
inputs: []string{"db/sept/migrate-v1.sql"},
367+
skipResult: false,
368+
filterResult: true,
369+
},
370+
{
371+
patterns: []string{"*.md", "!README.md"},
372+
inputs: []string{"hello.md"},
373+
skipResult: false,
374+
filterResult: true,
375+
},
376+
{
377+
patterns: []string{"*.md", "!README.md"},
378+
inputs: []string{"README.md"},
379+
skipResult: true,
380+
filterResult: true,
381+
},
382+
{
383+
patterns: []string{"*.md", "!README.md"},
384+
inputs: []string{"docs/hello.md"},
385+
skipResult: true,
386+
filterResult: true,
387+
},
388+
{
389+
patterns: []string{"*.md", "!README.md", "README*"},
390+
inputs: []string{"hello.md"},
391+
skipResult: false,
392+
filterResult: true,
393+
},
394+
{
395+
patterns: []string{"*.md", "!README.md", "README*"},
396+
inputs: []string{"README.md"},
397+
skipResult: false,
398+
filterResult: true,
399+
},
400+
{
401+
patterns: []string{"*.md", "!README.md", "README*"},
402+
inputs: []string{"README.doc"},
403+
skipResult: false,
404+
filterResult: true,
405+
},
406+
}
407+
408+
for _, kase := range kases {
409+
t.Run(strings.Join(kase.patterns, ","), func(t *testing.T) {
410+
patterns, err := CompilePatterns(kase.patterns...)
411+
assert.NoError(t, err)
412+
413+
assert.EqualValues(t, kase.skipResult, Skip(patterns, kase.inputs, &StdOutTraceWriter{}), "skipResult")
414+
assert.EqualValues(t, kase.filterResult, Filter(patterns, kase.inputs, &StdOutTraceWriter{}), "filterResult")
415+
})
416+
}
417+
}

‎modules/actions/workflows.go

+107-35
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"io"
99
"strings"
1010

11+
"code.gitea.io/gitea/modules/actions/workflowpattern"
1112
"code.gitea.io/gitea/modules/git"
1213
"code.gitea.io/gitea/modules/log"
1314
api "code.gitea.io/gitea/modules/structs"
@@ -100,40 +101,94 @@ func detectMatched(commit *git.Commit, triggedEvent webhook_module.HookEventType
100101
case webhook_module.HookEventPush:
101102
pushPayload := payload.(*api.PushPayload)
102103
matchTimes := 0
104+
hasBranchFilter := false
105+
hasTagFilter := false
106+
refName := git.RefName(pushPayload.Ref)
103107
// all acts conditions should be satisfied
104108
for cond, vals := range evt.Acts {
105109
switch cond {
106-
case "branches", "tags":
107-
refShortName := git.RefName(pushPayload.Ref).ShortName()
108-
for _, val := range vals {
109-
if glob.MustCompile(val, '/').Match(refShortName) {
110-
matchTimes++
110+
case "branches":
111+
hasBranchFilter = true
112+
if !refName.IsBranch() {
113+
break
114+
}
115+
patterns, err := workflowpattern.CompilePatterns(vals...)
116+
if err != nil {
117+
break
118+
}
119+
if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
120+
matchTimes++
121+
}
122+
case "branches-ignore":
123+
hasBranchFilter = true
124+
if !refName.IsBranch() {
125+
break
126+
}
127+
patterns, err := workflowpattern.CompilePatterns(vals...)
128+
if err != nil {
129+
break
130+
}
131+
if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
132+
matchTimes++
133+
}
134+
case "tags":
135+
hasTagFilter = true
136+
if !refName.IsTag() {
137+
break
138+
}
139+
patterns, err := workflowpattern.CompilePatterns(vals...)
140+
if err != nil {
141+
break
142+
}
143+
if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
144+
matchTimes++
145+
}
146+
case "tags-ignore":
147+
hasTagFilter = true
148+
if !refName.IsTag() {
149+
break
150+
}
151+
patterns, err := workflowpattern.CompilePatterns(vals...)
152+
if err != nil {
153+
break
154+
}
155+
if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
156+
matchTimes++
157+
}
158+
case "paths":
159+
filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before)
160+
if err != nil {
161+
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
162+
} else {
163+
patterns, err := workflowpattern.CompilePatterns(vals...)
164+
if err != nil {
111165
break
112166
}
167+
if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
168+
matchTimes++
169+
}
113170
}
114-
case "paths":
171+
case "paths-ignore":
115172
filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before)
116173
if err != nil {
117174
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
118175
} else {
119-
for _, val := range vals {
120-
matched := false
121-
for _, file := range filesChanged {
122-
if glob.MustCompile(val, '/').Match(file) {
123-
matched = true
124-
break
125-
}
126-
}
127-
if matched {
128-
matchTimes++
129-
break
130-
}
176+
patterns, err := workflowpattern.CompilePatterns(vals...)
177+
if err != nil {
178+
break
179+
}
180+
if !workflowpattern.Filter(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
181+
matchTimes++
131182
}
132183
}
133184
default:
134185
log.Warn("unsupported condition %q", cond)
135186
}
136187
}
188+
// if both branch and tag filter are defined in the workflow only one needs to match
189+
if hasBranchFilter && hasTagFilter {
190+
matchTimes++
191+
}
137192
return matchTimes == len(evt.Acts)
138193

139194
case webhook_module.HookEventIssues:
@@ -160,30 +215,47 @@ func detectMatched(commit *git.Commit, triggedEvent webhook_module.HookEventType
160215
}
161216
}
162217
case "branches":
163-
refShortName := git.RefName(prPayload.PullRequest.Base.Ref).ShortName()
164-
for _, val := range vals {
165-
if glob.MustCompile(val, '/').Match(refShortName) {
166-
matchTimes++
218+
refName := git.RefName(prPayload.PullRequest.Base.Ref)
219+
patterns, err := workflowpattern.CompilePatterns(vals...)
220+
if err != nil {
221+
break
222+
}
223+
if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
224+
matchTimes++
225+
}
226+
case "branches-ignore":
227+
refName := git.RefName(prPayload.PullRequest.Base.Ref)
228+
patterns, err := workflowpattern.CompilePatterns(vals...)
229+
if err != nil {
230+
break
231+
}
232+
if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
233+
matchTimes++
234+
}
235+
case "paths":
236+
filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref)
237+
if err != nil {
238+
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
239+
} else {
240+
patterns, err := workflowpattern.CompilePatterns(vals...)
241+
if err != nil {
167242
break
168243
}
244+
if !workflowpattern.Skip(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
245+
matchTimes++
246+
}
169247
}
170-
case "paths":
248+
case "paths-ignore":
171249
filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref)
172250
if err != nil {
173251
log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err)
174252
} else {
175-
for _, val := range vals {
176-
matched := false
177-
for _, file := range filesChanged {
178-
if glob.MustCompile(val, '/').Match(file) {
179-
matched = true
180-
break
181-
}
182-
}
183-
if matched {
184-
matchTimes++
185-
break
186-
}
253+
patterns, err := workflowpattern.CompilePatterns(vals...)
254+
if err != nil {
255+
break
256+
}
257+
if !workflowpattern.Filter(patterns, filesChanged, &workflowpattern.EmptyTraceWriter{}) {
258+
matchTimes++
187259
}
188260
}
189261
default:

0 commit comments

Comments
 (0)
Please sign in to comment.