Skip to content

Commit 0deb3cf

Browse files
Merge pull request #56 from jdavisp3/continue-processing
Add processAllRules option.
2 parents f7d2752 + 0bbc459 commit 0deb3cf

File tree

5 files changed

+109
-56
lines changed

5 files changed

+109
-56
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ gocd.slack {
2626
slackDisplayName = "gocd-slack-bot"
2727
slackUserIconURL = "http://example.com/slack-bot.png"
2828
displayMaterialChanges = true
29+
process-all-rules = true
2930
proxy {
3031
hostname = "localhost"
3132
port = "5555"
@@ -40,6 +41,7 @@ gocd.slack {
4041
- `webhookUrl` - Slack Webhook URL
4142
- `channel` - Override the default channel where we should send the notifications in slack. You can also give a value starting with `@` to send it to any specific user.
4243
- `displayMaterialChanges` - Display material changes in the notification (git revisions for example). Defaults to true, set to false if you want to hide.
44+
- `process-all-rules` - If true, all matching rules are applied instead of just the first.
4345
- `proxy` - Specify proxy related settings for the plugin.
4446
- `proxy.hostname` - Proxy Host
4547
- `proxy.port` - Proxy Port
@@ -67,7 +69,7 @@ gocd.slack {
6769
}]
6870
}
6971
```
70-
`gocd.slack.pipelines` contains all the rules for the go-server. It is a list of rules (see below for what the parameters mean) for various pipelines. The plugin will pick the first matching pipeline rule from the pipelines collection above, so your most specific rule should be first, with the most generic rule at the bottom.
72+
`gocd.slack.pipelines` contains all the rules for the go-server. It is a list of rules (see below for what the parameters mean) for various pipelines. The plugin will pick the first matching pipeline rule from the pipelines collection above, so your most specific rule should be first, with the most generic rule at the bottom. Alternatively, set the `process-all-rules` option to `true` and all matching rules will be applied.
7173
- `name` - Regex to match the pipeline name
7274
- `stage` - Regex to match the stage name
7375
- `state` - State of the pipeline at which we should send a notification. You can provide multiple values separated by pipe (`|`) symbol. Valid values are passed, failed, cancelled, building, fixed, broken or all.

docs/index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ gocd.slack {
2626
slackDisplayName = "gocd-slack-bot"
2727
slackUserIconURL = "http://example.com/slack-bot.png"
2828
displayMaterialChanges = true
29+
process-all-rules = true
2930
proxy {
3031
hostname = "localhost"
3132
port = "5555"
@@ -40,6 +41,7 @@ gocd.slack {
4041
- `webhookUrl` - Slack Webhook URL
4142
- `channel` - Override the default channel where we should send the notifications in slack. You can also give a value starting with `@` to send it to any specific user.
4243
- `displayMaterialChanges` - Display material changes in the notification (git revisions for example). Defaults to true, set to false if you want to hide.
44+
- `process-all-rules` - If true, all matching rules are applied instead of just the first.
4345
- `proxy` - Specify proxy related settings for the plugin.
4446
- `proxy.hostname` - Proxy Host
4547
- `proxy.port` - Proxy Port
@@ -67,7 +69,7 @@ gocd.slack {
6769
}]
6870
}
6971
```
70-
`gocd.slack.pipelines` contains all the rules for the go-server. It is a list of rules (see below for what the parameters mean) for various pipelines. The plugin will pick the first matching pipeline rule from the pipelines collection above, so your most specific rule should be first, with the most generic rule at the bottom.
72+
`gocd.slack.pipelines` contains all the rules for the go-server. It is a list of rules (see below for what the parameters mean) for various pipelines. The plugin will pick the first matching pipeline rule from the pipelines collection above, so your most specific rule should be first, with the most generic rule at the bottom. Alternatively, set the `process-all-rules` option to `true` and all matching rules will be applied.
7173
- `name` - Regex to match the pipeline name
7274
- `stage` - Regex to match the stage name
7375
- `state` - State of the pipeline at which we should send a notification. You can provide multiple values separated by pipe (`|`) symbol. Valid values are passed, failed, cancelled, building, fixed, broken or all.

src/main/java/in/ashwanthkumar/gocd/slack/PipelineListener.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import in.ashwanthkumar.gocd.slack.ruleset.Rules;
77
import in.ashwanthkumar.utils.lang.option.Option;
88

9+
import java.util.List;
10+
911
abstract public class PipelineListener {
1012
private Logger LOG = Logger.getLoggerFor(PipelineListener.class);
1113
protected Rules rules;
@@ -17,11 +19,15 @@ public PipelineListener(Rules rules) {
1719
public void notify(GoNotificationMessage message) throws Exception {
1820
message.tryToFixStageResult(rules);
1921
LOG.debug(String.format("Finding rules with state %s", message.getStageResult()));
20-
Option<PipelineRule> ruleOption = rules.find(message.getPipelineName(), message.getStageName(), message.getStageResult());
21-
if (ruleOption.isDefined()) {
22-
PipelineRule pipelineRule = ruleOption.get();
23-
LOG.debug(String.format("Matching rule is %s", pipelineRule));
24-
handlePipelineStatus(pipelineRule, PipelineStatus.valueOf(message.getStageResult().toUpperCase()), message);
22+
List<PipelineRule> foundRules = rules.find(message.getPipelineName(), message.getStageName(), message.getStageResult());
23+
if (foundRules.size() > 0) {
24+
for (PipelineRule pipelineRule : foundRules) {
25+
LOG.debug(String.format("Matching rule is %s", pipelineRule));
26+
handlePipelineStatus(pipelineRule, PipelineStatus.valueOf(message.getStageResult().toUpperCase()), message);
27+
if (! rules.getProcessAllRules()) {
28+
break;
29+
}
30+
}
2531
} else {
2632
LOG.warn(String.format("Couldn't find any matching rule for %s/%s with status=%s", message.getPipelineName(), message.getStageName(), message.getStageResult()));
2733
}

src/main/java/in/ashwanthkumar/gocd/slack/ruleset/Rules.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class Rules {
3030
private String goLogin;
3131
private String goPassword;
3232
private boolean displayMaterialChanges;
33+
private boolean processAllRules;
3334

3435
private Proxy proxy;
3536

@@ -139,6 +140,15 @@ public Rules setDisplayMaterialChanges(boolean displayMaterialChanges) {
139140
return this;
140141
}
141142

143+
public boolean getProcessAllRules() {
144+
return processAllRules;
145+
}
146+
147+
public Rules setProcessAllRules(boolean processAllRules) {
148+
this.processAllRules = processAllRules;
149+
return this;
150+
}
151+
142152
public Proxy getProxy() {
143153
return proxy;
144154
}
@@ -152,12 +162,23 @@ public PipelineListener getPipelineListener() {
152162
return pipelineListener;
153163
}
154164

155-
public Option<PipelineRule> find(final String pipeline, final String stage, final String pipelineStatus) {
156-
return Lists.find(pipelineRules, new Predicate<PipelineRule>() {
165+
public List<PipelineRule> find(final String pipeline, final String stage, final String pipelineStatus) {
166+
Predicate<PipelineRule> predicate = new Predicate<PipelineRule>() {
157167
public Boolean apply(PipelineRule input) {
158168
return input.matches(pipeline, stage, pipelineStatus);
159169
}
160-
});
170+
};
171+
172+
if(processAllRules) {
173+
return Lists.filter(pipelineRules, predicate);
174+
} else {
175+
List<PipelineRule> found = new ArrayList<PipelineRule>();
176+
Option<PipelineRule> match = Lists.find(pipelineRules, predicate);
177+
if(match.isDefined()) {
178+
found.add(match.get());
179+
}
180+
return found;
181+
}
161182
}
162183

163184
public static Rules fromConfig(Config config) {
@@ -199,6 +220,11 @@ public static Rules fromConfig(Config config) {
199220
displayMaterialChanges = config.getBoolean("displayMaterialChanges");
200221
}
201222

223+
boolean processAllRules = false;
224+
if (config.hasPath("process-all-rules")) {
225+
processAllRules = config.getBoolean("process-all-rules");
226+
}
227+
202228
Proxy proxy = null;
203229
if (config.hasPath("proxy")) {
204230
Config proxyConfig = config.getConfig("proxy");
@@ -231,6 +257,7 @@ public PipelineRule apply(Config input) {
231257
.setGoLogin(login)
232258
.setGoPassword(password)
233259
.setDisplayMaterialChanges(displayMaterialChanges)
260+
.setProcessAllRules(processAllRules)
234261
.setProxy(proxy);
235262
try {
236263
rules.pipelineListener = Class.forName(config.getString("listener")).asSubclass(PipelineListener.class).getConstructor(Rules.class).newInstance(rules);
Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package in.ashwanthkumar.gocd.slack.ruleset;
22

3-
43
import in.ashwanthkumar.gocd.slack.Status;
54
import in.ashwanthkumar.utils.lang.option.Option;
65
import org.junit.Test;
76

87
import java.util.Arrays;
8+
import java.util.List;
99
import java.util.HashSet;
1010
import java.util.Set;
1111

@@ -17,34 +17,30 @@ public class RulesTest {
1717
@Test
1818
public void shouldFindMatch() {
1919
Rules rules = new Rules();
20-
PipelineRule pRules1 = new PipelineRule("pipeline", "stage");
21-
pRules1.setStatus(new HashSet<PipelineStatus>(Arrays.asList(PipelineStatus.PASSED, PipelineStatus.FAILED)));
2220

2321
rules.setPipelineRules(Arrays.asList(
2422
pipelineRule("pipeline1", "stage1", "ch1", statuses(PipelineStatus.BUILDING, PipelineStatus.FAILED)),
2523
pipelineRule("pipeline1", "stage2", "ch2", statuses(PipelineStatus.FIXED, PipelineStatus.PASSED)),
2624
pipelineRule("pipeline2", "stage2", "ch3", statuses(PipelineStatus.CANCELLED, PipelineStatus.BROKEN))
2725
));
2826

29-
Option<PipelineRule> rule1 = rules.find("pipeline1", "stage1", Status.Building.getStatus());
30-
assertThat(rule1.isDefined(), is(true));
31-
assertThat(rule1.get().getNameRegex(), is("pipeline1"));
32-
assertThat(rule1.get().getStageRegex(), is("stage1"));
27+
List<PipelineRule> foundRules1 = rules.find("pipeline1", "stage1", Status.Building.getStatus());
28+
assertThat(foundRules1.size(), is(1));
29+
assertThat(foundRules1.get(0).getNameRegex(), is("pipeline1"));
30+
assertThat(foundRules1.get(0).getStageRegex(), is("stage1"));
3331

34-
Option<PipelineRule> rule2 = rules.find("pipeline2", "stage2", Status.Cancelled.getStatus());
35-
assertThat(rule2.isDefined(), is(true));
36-
assertThat(rule2.get().getNameRegex(), is("pipeline2"));
37-
assertThat(rule2.get().getStageRegex(), is("stage2"));
32+
List<PipelineRule> foundRules2 = rules.find("pipeline2", "stage2", Status.Cancelled.getStatus());
33+
assertThat(foundRules2.size(), is(1));
34+
assertThat(foundRules2.get(0).getNameRegex(), is("pipeline2"));
35+
assertThat(foundRules2.get(0).getStageRegex(), is("stage2"));
3836

39-
Option<PipelineRule> rule3 = rules.find("pipeline2", "stage2", Status.Passed.getStatus());
40-
assertThat(rule3.isDefined(), is(false));
37+
List<PipelineRule> foundRules3 = rules.find("pipeline2", "stage2", Status.Passed.getStatus());
38+
assertThat(foundRules3.size(), is(0));
4139
}
4240

4341
@Test
4442
public void shouldFindMatchWithRegexp() {
4543
Rules rules = new Rules();
46-
PipelineRule pRules1 = new PipelineRule("pipeline", "stage");
47-
pRules1.setStatus(new HashSet<PipelineStatus>(Arrays.asList(PipelineStatus.PASSED, PipelineStatus.FAILED)));
4844

4945
rules.setPipelineRules(Arrays.asList(
5046
pipelineRule("[a-z]*", "[a-z]*", "ch1", statuses(PipelineStatus.BUILDING)),
@@ -53,46 +49,66 @@ public void shouldFindMatchWithRegexp() {
5349
pipelineRule("\\d*", "[a-z]*", "ch4", statuses(PipelineStatus.BUILDING))
5450
));
5551

56-
Option<PipelineRule> rule1 = rules.find("abc", "efg", Status.Building.getStatus());
57-
assertThat(rule1.isDefined(), is(true));
58-
assertThat(rule1.get().getNameRegex(), is("[a-z]*"));
59-
assertThat(rule1.get().getStageRegex(), is("[a-z]*"));
60-
assertThat(rule1.get().getChannel(), is("ch1"));
61-
62-
Option<PipelineRule> rule2 = rules.find("123", "456", Status.Building.getStatus());
63-
assertThat(rule2.isDefined(), is(true));
64-
assertThat(rule2.get().getNameRegex(), is("\\d*"));
65-
assertThat(rule2.get().getStageRegex(), is("\\d*"));
66-
assertThat(rule2.get().getChannel(), is("ch2"));
67-
68-
Option<PipelineRule> rule3 = rules.find("123", "456", Status.Passed.getStatus());
69-
assertThat(rule3.isDefined(), is(true));
70-
assertThat(rule3.get().getNameRegex(), is("\\d*"));
71-
assertThat(rule3.get().getStageRegex(), is("\\d*"));
72-
assertThat(rule3.get().getChannel(), is("ch3"));
73-
74-
Option<PipelineRule> rule4 = rules.find("pipeline1", "stage1", Status.Passed.getStatus());
75-
assertThat(rule4.isDefined(), is(false));
52+
List<PipelineRule> foundRules1 = rules.find("abc", "efg", Status.Building.getStatus());
53+
assertThat(foundRules1.size(), is(1));
54+
assertThat(foundRules1.get(0).getNameRegex(), is("[a-z]*"));
55+
assertThat(foundRules1.get(0).getStageRegex(), is("[a-z]*"));
56+
assertThat(foundRules1.get(0).getChannel(), is("ch1"));
57+
58+
List<PipelineRule> foundRules2 = rules.find("123", "456", Status.Building.getStatus());
59+
assertThat(foundRules2.size(), is(1));
60+
assertThat(foundRules2.get(0).getNameRegex(), is("\\d*"));
61+
assertThat(foundRules2.get(0).getStageRegex(), is("\\d*"));
62+
assertThat(foundRules2.get(0).getChannel(), is("ch2"));
63+
64+
List<PipelineRule> foundRules3 = rules.find("123", "456", Status.Passed.getStatus());
65+
assertThat(foundRules3.size(), is(1));
66+
assertThat(foundRules3.get(0).getNameRegex(), is("\\d*"));
67+
assertThat(foundRules3.get(0).getStageRegex(), is("\\d*"));
68+
assertThat(foundRules3.get(0).getChannel(), is("ch3"));
69+
70+
List<PipelineRule> foundRules4 = rules.find("pipeline1", "stage1", Status.Passed.getStatus());
71+
assertThat(foundRules4.size(), is(0));
72+
}
73+
@Test
74+
public void shouldFindAllMatchesIfProcessAllRules() {
75+
Rules rules = new Rules();
76+
rules.setProcessAllRules(true);
77+
78+
rules.setPipelineRules(Arrays.asList(
79+
pipelineRule("[a-z]*", "stage\\d+", "ch1", statuses(PipelineStatus.BUILDING)),
80+
pipelineRule("[a-z]*", "stage2", "ch2", statuses(PipelineStatus.BUILDING))
81+
));
82+
83+
List<PipelineRule> foundRules1 = rules.find("abc", "stage1", Status.Building.getStatus());
84+
assertThat(foundRules1.size(), is(1));
85+
assertThat(foundRules1.get(0).getChannel(), is("ch1"));
86+
87+
List<PipelineRule> foundRules2 = rules.find("abc", "stage2", Status.Building.getStatus());
88+
assertThat(foundRules2.size(), is(2));
89+
assertThat(foundRules2.get(0).getChannel(), is("ch1"));
90+
assertThat(foundRules2.get(1).getChannel(), is("ch2"));
91+
92+
List<PipelineRule> foundRules3 = rules.find("abc1", "stage2", Status.Building.getStatus());
93+
assertThat(foundRules3.size(), is(0));
7694
}
7795

7896
@Test
7997
public void shouldFindMatchAll() {
8098
Rules rules = new Rules();
81-
PipelineRule pRules1 = new PipelineRule("pipeline", "stage");
82-
pRules1.setStatus(new HashSet<PipelineStatus>(Arrays.asList(PipelineStatus.PASSED, PipelineStatus.FAILED)));
8399

84100
rules.setPipelineRules(Arrays.asList(
85101
pipelineRule("p1", "s1", "ch1", statuses(PipelineStatus.ALL))
86102
));
87103

88-
assertThat(rules.find("p1", "s1", Status.Building.getStatus()).isDefined(), is(true));
89-
assertThat(rules.find("p1", "s1", Status.Broken.getStatus()).isDefined(), is(true));
90-
assertThat(rules.find("p1", "s1", Status.Cancelled.getStatus()).isDefined(), is(true));
91-
assertThat(rules.find("p1", "s1", Status.Failed.getStatus()).isDefined(), is(true));
92-
assertThat(rules.find("p1", "s1", Status.Failing.getStatus()).isDefined(), is(true));
93-
assertThat(rules.find("p1", "s1", Status.Fixed.getStatus()).isDefined(), is(true));
94-
assertThat(rules.find("p1", "s1", Status.Passed.getStatus()).isDefined(), is(true));
95-
assertThat(rules.find("p1", "s1", Status.Unknown.getStatus()).isDefined(), is(true));
104+
assertThat(rules.find("p1", "s1", Status.Building.getStatus()).size(), is(1));
105+
assertThat(rules.find("p1", "s1", Status.Broken.getStatus()).size(), is(1));
106+
assertThat(rules.find("p1", "s1", Status.Cancelled.getStatus()).size(), is(1));
107+
assertThat(rules.find("p1", "s1", Status.Failed.getStatus()).size(), is(1));
108+
assertThat(rules.find("p1", "s1", Status.Failing.getStatus()).size(), is(1));
109+
assertThat(rules.find("p1", "s1", Status.Fixed.getStatus()).size(), is(1));
110+
assertThat(rules.find("p1", "s1", Status.Passed.getStatus()).size(), is(1));
111+
assertThat(rules.find("p1", "s1", Status.Unknown.getStatus()).size(), is(1));
96112
}
97113

98114
@Test
@@ -117,4 +133,4 @@ private static Set<PipelineStatus> statuses(PipelineStatus... statuses) {
117133
return new HashSet<PipelineStatus>(Arrays.asList(statuses));
118134
}
119135

120-
}
136+
}

0 commit comments

Comments
 (0)