Skip to content

Commit 6561333

Browse files
committed
rename filter to files and add issue title condition
1 parent 039f60c commit 6561333

File tree

5 files changed

+101
-15
lines changed

5 files changed

+101
-15
lines changed

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,16 @@ rules:
102102
- label2
103103
skip-if-labeled:
104104
- label3
105-
filter:
105+
files:
106106
patterns:
107107
- "docs/.*"
108108
extensions:
109109
- ".go"
110+
title:
111+
starts-with: "BUGFIX"
112+
ends-with: "WIP"
113+
patterns:
114+
- ".* Bug( )?[0-9]{5} .*"
110115
order: 5
111116
commenter:
112117
comment: "We have a match!"
@@ -118,9 +123,13 @@ rules:
118123
The entire `condition` section is optional - you can run all rules all the time and see if it helps :smile:
119124
- `if-labeled` - apply the rule if the issue has any of the provided labels
120125
- `skip-if-labeled` - skip rule processing if issue has any of the provided labels
121-
- `filter`
126+
- `files`
122127
- `patterns` - [pattern](https://golang.org/s/re2syntax) matching the pull request file list (any of the patterns)
123128
- `extensions` - which file extension to match on pull request file list (must start with a dot [`.`])
129+
- `title`
130+
- `starts-with` - issue title has a prefix
131+
- `ends-with` - issue title has a suffix
132+
- `patterns` - [pattern](https://golang.org/s/re2syntax) matching issue title (any of the patterns)
124133
- `order` - apply order hint to a rule. All rules are given order index **0**.
125134
**Important**: This will not place a rule in the exact position, but can assist in re-order rules.
126135

@@ -166,7 +175,7 @@ rules:
166175
167176
docs:
168177
condition:
169-
filter:
178+
files:
170179
patterns:
171180
- "docs/.*"
172181
labeler:

bot/condition.go

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,22 @@ import (
44
"github.com/bivas/rivi/util"
55
"github.com/spf13/viper"
66
"regexp"
7+
"strings"
78
)
89

910
type Condition struct {
1011
Order int `mapstructure:"order,omitempty"`
1112
IfLabeled []string `mapstructure:"if-labeled,omitempty"`
1213
SkipIfLabeled []string `mapstructure:"skip-if-labeled,omitempty"`
13-
Filter struct {
14+
Files struct {
1415
Patterns []string `mapstructure:"patterns,omitempty"`
1516
Extensions []string `mapstructure:"extensions,omitempty"`
16-
} `mapstructure:"filter,omitempty"`
17+
} `mapstructure:"files,omitempty"`
18+
Title struct {
19+
StartsWith string `mapstructure:"starts-with,omitempty"`
20+
EndsWith string `mapstructure:"ends-with,omitempty"`
21+
Patterns []string `mapstructure:"patterns,omitempty"`
22+
} `mapstructure:"title,omitempty"`
1723
}
1824

1925
func (c *Condition) checkIfLabeled(meta EventData) bool {
@@ -32,11 +38,11 @@ func (c *Condition) checkIfLabeled(meta EventData) bool {
3238
}
3339

3440
func (c *Condition) checkPattern(meta EventData) bool {
35-
if len(c.Filter.Patterns) == 0 {
41+
if len(c.Files.Patterns) == 0 {
3642
return false
3743
} else {
3844
compiled := make([]*regexp.Regexp, 0)
39-
for _, pattern := range c.Filter.Patterns {
45+
for _, pattern := range c.Files.Patterns {
4046
re, err := regexp.Compile(pattern)
4147
if err != nil {
4248
util.Logger.Warning("Unable to compile regex '%s'. %s", pattern, err)
@@ -60,11 +66,11 @@ func (c *Condition) checkPattern(meta EventData) bool {
6066
}
6167

6268
func (c *Condition) checkExt(meta EventData) bool {
63-
if len(c.Filter.Extensions) == 0 {
69+
if len(c.Files.Extensions) == 0 {
6470
return false
6571
} else {
6672
for _, check := range meta.GetFileExtensions() {
67-
for _, ext := range c.Filter.Extensions {
73+
for _, ext := range c.Files.Extensions {
6874
if ext == check {
6975
return true
7076
}
@@ -74,12 +80,54 @@ func (c *Condition) checkExt(meta EventData) bool {
7480
return false
7581
}
7682

83+
func (c *Condition) checkTitle(meta EventData) bool {
84+
titleCondition := c.Title
85+
if titleCondition.StartsWith == "" && titleCondition.EndsWith == "" && len(titleCondition.Patterns) == 0 {
86+
return false
87+
} else {
88+
title := meta.GetTitle()
89+
if titleCondition.StartsWith != "" && strings.HasPrefix(title, titleCondition.StartsWith) {
90+
return true
91+
}
92+
if titleCondition.EndsWith != "" && strings.HasSuffix(title, titleCondition.EndsWith) {
93+
return true
94+
}
95+
if len(titleCondition.Patterns) > 0 {
96+
compiled := make([]*regexp.Regexp, 0)
97+
for _, pattern := range titleCondition.Patterns {
98+
re, err := regexp.Compile(pattern)
99+
if err != nil {
100+
util.Logger.Warning("Unable to compile regex '%s'. %s", pattern, err)
101+
continue
102+
}
103+
compiled = append(compiled, re)
104+
}
105+
if len(compiled) == 0 {
106+
util.Logger.Error("All configured patterns have failed to compile")
107+
return false
108+
}
109+
for _, reg := range compiled {
110+
if reg.MatchString(title) {
111+
return true
112+
}
113+
}
114+
}
115+
}
116+
return false
117+
}
118+
119+
func (c *Condition) checkFiles(meta EventData) bool {
120+
return c.checkPattern(meta) || c.checkExt(meta)
121+
}
122+
77123
func (c *Condition) checkAllEmpty(meta EventData) bool {
78-
return len(c.IfLabeled) == 0 && len(c.Filter.Patterns) == 0 && len(c.Filter.Extensions) == 0
124+
return len(c.IfLabeled) == 0 &&
125+
len(c.Files.Patterns) == 0 && len(c.Files.Extensions) == 0 &&
126+
c.Title.StartsWith == "" && c.Title.EndsWith == "" && len(c.Title.Patterns) == 0
79127
}
80128

81129
func (c *Condition) Match(meta EventData) bool {
82-
match := c.checkAllEmpty(meta) || c.checkIfLabeled(meta) || c.checkPattern(meta) || c.checkExt(meta)
130+
match := c.checkAllEmpty(meta) || c.checkIfLabeled(meta) || c.checkTitle(meta) || c.checkFiles(meta)
83131

84132
if match {
85133
for _, check := range c.SkipIfLabeled {

bot/condition_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,35 @@ func TestMatchExt(t *testing.T) {
156156
assert.True(t, matched, "matched")
157157
}
158158

159+
func TestTitleStartsWith(t *testing.T) {
160+
var rule rule
161+
rule.condition.Title.StartsWith = "BUGFIX"
162+
meta := &mockConditionEventData{Title: "NOT A BUGFIX"}
163+
assert.False(t, rule.Accept(meta), "shouldn't match")
164+
meta.Title = "BUGFIX it"
165+
assert.True(t, rule.Accept(meta), "should match")
166+
}
167+
168+
func TestTitleEndsWith(t *testing.T) {
169+
var rule rule
170+
rule.condition.Title.EndsWith = "WIP"
171+
meta := &mockConditionEventData{Title: "NOT A BUGFIX"}
172+
assert.False(t, rule.Accept(meta), "shouldn't match")
173+
meta.Title = "BUGFIX WIP"
174+
assert.True(t, rule.Accept(meta), "should match")
175+
}
176+
177+
func TestTitlePattern(t *testing.T) {
178+
var rule rule
179+
rule.condition.Title.Patterns = []string{".* Bug( )?[0-9]{5} .*"}
180+
meta := &mockConditionEventData{Title: "NOT A BUGFIX"}
181+
assert.False(t, rule.Accept(meta), "shouldn't match")
182+
meta.Title = "This PR for Bug1 with comment"
183+
assert.False(t, rule.Accept(meta), "shouldn't match")
184+
meta.Title = "This PR for Bug 45456 with comment"
185+
assert.True(t, rule.Accept(meta), "should match")
186+
}
187+
159188
func TestMatchEmptyCondition(t *testing.T) {
160189
meta := &mockConditionEventData{}
161190
rule := rule{condition: Condition{}}

bot/config_test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ rules:
2929
rule3:
3030
condition:
3131
order: 1
32-
filter:
32+
files:
3333
extensions:
3434
- ".go"
3535
rule4:
3636
condition:
37-
filter:
37+
files:
3838
patterns:
3939
- ".*/docs/.*"

bot/empty_config_test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ rules:
2424
rule3:
2525
condition:
2626
order: 1
27-
filter:
27+
files:
2828
extensions:
2929
- ".go"
3030
rule4:
3131
condition:
32-
filter:
32+
files:
3333
patterns:
3434
- ".*/docs/.*"

0 commit comments

Comments
 (0)