Skip to content
This repository was archived by the owner on Jun 9, 2021. It is now read-only.

Commit 60bea78

Browse files
committed
Adding support for PULL_REQUEST_FROM/TO_HASH, filters and fixing authentication bug
* Making it compatible with Stash 2.12.0 * Some more documentation * Validating regexp * Log events
1 parent c6d4164 commit 60bea78

19 files changed

+548
-243
lines changed

CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Pull Request Notifier for Stash Changelog
22

3-
Changelog of Pull Request Notifier for Stash
3+
Changelog of Pull Request Notifier for Stash.
4+
5+
## 1.1
6+
7+
* Adding support for filters
8+
* Adding support for PULL_REQUEST_TO_HASH and PULL_REQUEST_FROM_HASH variables
9+
* Fixing authentication bug
10+
* Making it compatible with Stash 2.12.0
411

512
## 1.0
613

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@ http://server/job/theJob/buildWithParameters?token=TOKEN&PARAMETER=Value
88

99
[Here](https://raw.githubusercontent.com/tomasbjerre/pull-request-notifier-for-stash/master/sandbox/all.png) is a screenshot of the admin GUI.
1010

11+
Available in [Atlassian Marketplace](https://marketplace.atlassian.com/plugins/se.bjurr.prnfs.pull-request-notifier-for-stash).
12+
1113
## Features
1214
The Pull Request Notifier for Stash can
1315

14-
* Invoke any URL when a pull request event happens.
16+
* Invoke any URL, or set of URL:s, when a pull request event happens.
1517
* With variables available to add necessary parameters.
1618
* Be configured to trigger on any pull request event.
19+
* Be configured to only trigger only if the pull request mathches a filter. Where a filter can target (among other things) branch, project or repo.
1720
* Authenticate with HTTP BASIC authentication.
1821

1922
## Developer instructions

sandbox/all.png

65.3 KB
Loading

sandbox/closer.png

12.2 KB
Loading

src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ public final class AdminFormValues extends ArrayList<Map<String, String>> {
1515
public static final String VALUE = "value";
1616

1717
public enum FIELDS {
18-
user, password, events, FORM_IDENTIFIER, url
18+
user, password, events, FORM_IDENTIFIER, url, filter_string, filter_regexp
1919
}
2020
}

src/main/java/se/bjurr/prnfs/admin/ConfigResource.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@
3535

3636
@Path("/")
3737
public class ConfigResource {
38+
private static final Logger logger = LoggerFactory.getLogger(ConfigResource.class);
3839
private final PluginSettingsFactory pluginSettingsFactory;
3940
private final TransactionTemplate transactionTemplate;
40-
private static final Logger logger = LoggerFactory.getLogger(ConfigResource.class);
4141
private final UserManager userManager;
4242

4343
public ConfigResource(UserManager userManager, PluginSettingsFactory pluginSettingsFactory,

src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package se.bjurr.prnfs.listener;
22

33
import static com.google.common.cache.CacheBuilder.newBuilder;
4+
import static com.google.common.collect.Lists.newArrayList;
45
import static java.lang.Boolean.FALSE;
56
import static java.lang.Boolean.TRUE;
7+
import static java.util.Collections.sort;
68
import static java.util.concurrent.TimeUnit.MILLISECONDS;
9+
import static java.util.regex.Pattern.compile;
710
import static se.bjurr.prnfs.settings.SettingsStorage.getPrnfsSettings;
811

12+
import java.util.ArrayList;
13+
914
import org.slf4j.Logger;
1015
import org.slf4j.LoggerFactory;
1116

17+
import se.bjurr.prnfs.listener.PrnfsRenderer.PrnfsVariable;
1218
import se.bjurr.prnfs.settings.PrnfsNotification;
1319
import se.bjurr.prnfs.settings.PrnfsSettings;
1420
import se.bjurr.prnfs.settings.ValidationException;
@@ -41,18 +47,34 @@ public void anEvent(PullRequestEvent o) {
4147
if (dublicateEventBug(o)) {
4248
return;
4349
}
50+
final PrnfsRenderer renderer = new PrnfsRenderer(o);
51+
logEvent(renderer, o);
4452
try {
4553
final PrnfsSettings settings = getPrnfsSettings(pluginSettingsFactory.createGlobalSettings());
4654
for (final PrnfsNotification n : settings.getNotifications()) {
55+
if (n.getFilterRegexp().isPresent() && n.getFilterString().isPresent()
56+
&& !compile(n.getFilterRegexp().get()).matcher(renderer.render(n.getFilterString().get())).find()) {
57+
continue;
58+
}
4759
if (n.getTriggers().contains(o.getAction())) {
48-
urlInvoker.ivoke(new PrnfsRenderer(o).render(n.getUrl()), n.getUser(), n.getPassword());
60+
urlInvoker.ivoke(renderer.render(n.getUrl()), n.getUser(), n.getPassword());
4961
}
5062
}
5163
} catch (final ValidationException e) {
5264
logger.error("", e);
5365
}
5466
}
5567

68+
private void logEvent(PrnfsRenderer renderer, PullRequestEvent o) {
69+
final StringBuilder renderString = new StringBuilder();
70+
final ArrayList<PrnfsVariable> variables = newArrayList(PrnfsRenderer.PrnfsVariable.values());
71+
sort(variables);
72+
for (final PrnfsRenderer.PrnfsVariable variable : variables) {
73+
renderString.append(" " + variable.name() + ": ${" + variable.name() + "}");
74+
}
75+
logger.info(renderer.render(renderString.toString().trim()));
76+
}
77+
5678
/**
5779
* Looks like there is a bug in Stash that causes events to be fired twice.
5880
*/

src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java

+39-29
Original file line numberDiff line numberDiff line change
@@ -4,80 +4,81 @@
44

55
public class PrnfsRenderer {
66

7-
public interface Resolver {
8-
public String resolve(PullRequestEvent pullRequestEvent);
9-
}
10-
117
public enum PrnfsVariable {
12-
PULL_REQUEST_ID(new Resolver() {
8+
PULL_REQUEST_FROM_HASH(new Resolver() {
139
@Override
1410
public String resolve(PullRequestEvent pullRequestEvent) {
15-
return pullRequestEvent.getPullRequest().getId() + "";
11+
return pullRequestEvent.getPullRequest().getFromRef().getLatestChangeset();
1612
}
17-
}), PULL_REQUEST_FROM_HASH(new Resolver() {
13+
}), PULL_REQUEST_FROM_ID(new Resolver() {
1814
@Override
1915
public String resolve(PullRequestEvent pullRequestEvent) {
20-
return pullRequestEvent.getPullRequest().getFromRef().getLatestCommit();
16+
return pullRequestEvent.getPullRequest().getFromRef().getId();
2117
}
22-
}), PULL_REQUEST_FROM_ID(new Resolver() {
18+
}), PULL_REQUEST_FROM_REPO_ID(new Resolver() {
2319
@Override
2420
public String resolve(PullRequestEvent pullRequestEvent) {
25-
return pullRequestEvent.getPullRequest().getFromRef().getId();
21+
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getId() + "";
22+
}
23+
}), PULL_REQUEST_FROM_REPO_NAME(new Resolver() {
24+
@Override
25+
public String resolve(PullRequestEvent pullRequestEvent) {
26+
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getName() + "";
2627
}
2728
}), PULL_REQUEST_FROM_REPO_PROJECT_ID(new Resolver() {
2829
@Override
2930
public String resolve(PullRequestEvent pullRequestEvent) {
3031
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getProject().getId() + "";
3132
}
32-
}), PULL_REQUEST_TO_REPO_PROJECT_ID(new Resolver() {
33+
}), PULL_REQUEST_FROM_REPO_PROJECT_KEY(new Resolver() {
3334
@Override
3435
public String resolve(PullRequestEvent pullRequestEvent) {
35-
return pullRequestEvent.getPullRequest().getToRef().getRepository().getProject().getId() + "";
36+
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getProject().getKey();
3637
}
37-
}), PULL_REQUEST_FROM_REPO_ID(new Resolver() {
38+
}), PULL_REQUEST_FROM_REPO_SLUG(new Resolver() {
3839
@Override
3940
public String resolve(PullRequestEvent pullRequestEvent) {
40-
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getId() + "";
41+
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getSlug() + "";
4142
}
42-
}), PULL_REQUEST_TO_REPO_ID(new Resolver() {
43+
}), PULL_REQUEST_ID(new Resolver() {
4344
@Override
4445
public String resolve(PullRequestEvent pullRequestEvent) {
45-
return pullRequestEvent.getPullRequest().getToRef().getRepository().getId() + "";
46+
return pullRequestEvent.getPullRequest().getId() + "";
4647
}
47-
}), PULL_REQUEST_FROM_REPO_NAME(new Resolver() {
48+
}), PULL_REQUEST_TO_HASH(new Resolver() {
4849
@Override
4950
public String resolve(PullRequestEvent pullRequestEvent) {
50-
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getName() + "";
51+
return pullRequestEvent.getPullRequest().getToRef().getLatestChangeset();
5152
}
52-
}), PULL_REQUEST_TO_REPO_NAME(new Resolver() {
53+
}), PULL_REQUEST_TO_ID(new Resolver() {
5354
@Override
5455
public String resolve(PullRequestEvent pullRequestEvent) {
55-
return pullRequestEvent.getPullRequest().getToRef().getRepository().getName() + "";
56+
return pullRequestEvent.getPullRequest().getToRef().getId();
5657
}
57-
}), PULL_REQUEST_FROM_REPO_SLUG(new Resolver() {
58+
}), PULL_REQUEST_TO_REPO_ID(new Resolver() {
5859
@Override
5960
public String resolve(PullRequestEvent pullRequestEvent) {
60-
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getSlug() + "";
61+
return pullRequestEvent.getPullRequest().getToRef().getRepository().getId() + "";
6162
}
62-
}), PULL_REQUEST_TO_REPO_SLUG(new Resolver() {
63+
}), PULL_REQUEST_TO_REPO_NAME(new Resolver() {
6364
@Override
6465
public String resolve(PullRequestEvent pullRequestEvent) {
65-
return pullRequestEvent.getPullRequest().getToRef().getRepository().getSlug() + "";
66+
return pullRequestEvent.getPullRequest().getToRef().getRepository().getName() + "";
6667
}
67-
}), PULL_REQUEST_FROM_REPO_PROJECT_KEY(new Resolver() {
68+
}), PULL_REQUEST_TO_REPO_PROJECT_ID(new Resolver() {
6869
@Override
6970
public String resolve(PullRequestEvent pullRequestEvent) {
70-
return pullRequestEvent.getPullRequest().getFromRef().getRepository().getProject().getKey();
71+
return pullRequestEvent.getPullRequest().getToRef().getRepository().getProject().getId() + "";
7172
}
7273
}), PULL_REQUEST_TO_REPO_PROJECT_KEY(new Resolver() {
7374
@Override
7475
public String resolve(PullRequestEvent pullRequestEvent) {
7576
return pullRequestEvent.getPullRequest().getToRef().getRepository().getProject().getKey();
7677
}
77-
}), PULL_REQUEST_TO_ID(new Resolver() {
78+
}), PULL_REQUEST_TO_REPO_SLUG(new Resolver() {
7879
@Override
7980
public String resolve(PullRequestEvent pullRequestEvent) {
80-
return pullRequestEvent.getPullRequest().getToRef().getId();
81+
return pullRequestEvent.getPullRequest().getToRef().getRepository().getSlug() + "";
8182
}
8283
});
8384

@@ -92,6 +93,10 @@ public String resolve(PullRequestEvent pullRequestEvent) {
9293
}
9394
}
9495

96+
public interface Resolver {
97+
public String resolve(PullRequestEvent pullRequestEvent);
98+
}
99+
95100
private final PullRequestEvent pullRequestEvent;
96101

97102
public PrnfsRenderer(PullRequestEvent pullRequestEvent) {
@@ -102,7 +107,12 @@ public String render(String string) {
102107
for (final PrnfsVariable variable : PrnfsVariable.values()) {
103108
final String regExpStr = "\\$\\{" + variable.name() + "\\}";
104109
if (string.contains(regExpStr.replaceAll("\\\\", ""))) {
105-
string = string.replaceAll(regExpStr, variable.resolve(pullRequestEvent));
110+
try {
111+
string = string.replaceAll(regExpStr, variable.resolve(pullRequestEvent));
112+
} catch (final NullPointerException e) {
113+
// So that all values does not need to be set for all test cases
114+
return string;
115+
}
106116
}
107117
}
108118
return string;

src/main/java/se/bjurr/prnfs/settings/PrnfsNotification.java

+31-4
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,60 @@
33
import static com.google.common.base.Optional.fromNullable;
44
import static com.google.common.base.Preconditions.checkNotNull;
55
import static com.google.common.base.Strings.nullToEmpty;
6+
import static java.util.regex.Pattern.compile;
67

78
import java.net.URL;
89
import java.util.List;
910

11+
import se.bjurr.prnfs.admin.AdminFormValues;
12+
1013
import com.atlassian.stash.pull.PullRequestAction;
1114
import com.google.common.base.Optional;
1215

1316
public class PrnfsNotification {
17+
private final String filterRegexp;
18+
private final String filterString;
1419
private final String password;
1520
private final List<PullRequestAction> triggers;
1621
private final String url;
1722
private final String user;
1823

19-
public PrnfsNotification(List<PullRequestAction> triggers, String password, String url, String user)
20-
throws ValidationException {
24+
public PrnfsNotification(List<PullRequestAction> triggers, String url, String user, String password,
25+
String filterString, String filterRegexp) throws ValidationException {
2126
this.password = nullToEmpty(password).trim();
2227
if (nullToEmpty(url).trim().isEmpty()) {
23-
throw new ValidationException("url", "URL not set!");
28+
throw new ValidationException(AdminFormValues.FIELDS.url.name(), "URL not set!");
2429
}
2530
try {
2631
new URL(url);
2732
} catch (final Exception e) {
28-
throw new ValidationException("url", "URL not valid!");
33+
throw new ValidationException(AdminFormValues.FIELDS.url.name(), "URL not valid!");
34+
}
35+
if (!nullToEmpty(filterRegexp).trim().isEmpty()) {
36+
try {
37+
compile(filterRegexp);
38+
} catch (final Exception e) {
39+
throw new ValidationException(AdminFormValues.FIELDS.filter_regexp.name(), "Filter regexp not valid! "
40+
+ e.getMessage().replaceAll("\n", " "));
41+
}
42+
if (nullToEmpty(filterString).trim().isEmpty()) {
43+
throw new ValidationException(AdminFormValues.FIELDS.filter_string.name(),
44+
"Filter string not set, nothing to match regexp against!");
45+
}
2946
}
3047
this.url = url;
3148
this.user = nullToEmpty(user).trim();
3249
this.triggers = checkNotNull(triggers);
50+
this.filterString = filterString;
51+
this.filterRegexp = filterRegexp;
52+
}
53+
54+
public Optional<String> getFilterRegexp() {
55+
return fromNullable(filterRegexp);
56+
}
57+
58+
public Optional<String> getFilterString() {
59+
return fromNullable(filterString);
3360
}
3461

3562
public Optional<String> getPassword() {

src/main/java/se/bjurr/prnfs/settings/PrnfsNotificationBuilder.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,31 @@ public static PrnfsNotificationBuilder prnfsNotificationBuilder() {
1616
private final List<PullRequestAction> triggers = newArrayList();
1717
private String url;
1818
private String user;
19+
private String filterRegexp;
20+
private String filterString;
1921

2022
private PrnfsNotificationBuilder() {
2123
}
2224

2325
public PrnfsNotification build() throws ValidationException {
24-
return new PrnfsNotification(triggers, password, url, user);
26+
return new PrnfsNotification(triggers, url, user, password, filterString, filterRegexp);
2527
}
2628

2729
public PrnfsNotificationBuilder withPassword(String password) {
2830
this.password = checkNotNull(password);
2931
return this;
3032
}
3133

34+
public PrnfsNotificationBuilder withFilterRegexp(String filterRegexp) {
35+
this.filterRegexp = checkNotNull(filterRegexp);
36+
return this;
37+
}
38+
39+
public PrnfsNotificationBuilder withFilterString(String filterString) {
40+
this.filterString = checkNotNull(filterString);
41+
return this;
42+
}
43+
3244
public PrnfsNotificationBuilder withTrigger(PullRequestAction trigger) {
3345
this.triggers.add(checkNotNull(trigger));
3446
return this;

src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java

+16-2
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ public class SettingsStorage {
4040
private static final Gson gson = new Gson();
4141
private static final Logger logger = LoggerFactory.getLogger(SettingsStorage.class);
4242

43-
private static final String STORAGE_KEY = AdminFormValues.class.getName() + "_2";
44-
4543
private static Random random = new Random(currentTimeMillis());
4644

45+
private static final String STORAGE_KEY = AdminFormValues.class.getName() + "_2";
46+
4747
public static void deleteSettings(PluginSettings pluginSettings, String id) {
4848
final Map<String, AdminFormValues> map = getNotificationsMap(pluginSettings);
4949
map.remove(id);
@@ -94,6 +94,20 @@ public static PrnfsNotification getPrnfsNotification(AdminFormValues a) throws V
9494
for (final Map<String, String> event : events) {
9595
prnfsNotificationBuilder.withTrigger(PullRequestAction.valueOf(event.get(VALUE)));
9696
}
97+
if (tryFind(a, predicate(AdminFormValues.FIELDS.user.name())).isPresent()) {
98+
prnfsNotificationBuilder.withUser(find(a, predicate(AdminFormValues.FIELDS.user.name())).get(VALUE));
99+
}
100+
if (tryFind(a, predicate(AdminFormValues.FIELDS.password.name())).isPresent()) {
101+
prnfsNotificationBuilder.withPassword(find(a, predicate(AdminFormValues.FIELDS.password.name())).get(VALUE));
102+
}
103+
if (tryFind(a, predicate(AdminFormValues.FIELDS.filter_string.name())).isPresent()) {
104+
prnfsNotificationBuilder
105+
.withFilterString(find(a, predicate(AdminFormValues.FIELDS.filter_string.name())).get(VALUE));
106+
}
107+
if (tryFind(a, predicate(AdminFormValues.FIELDS.filter_regexp.name())).isPresent()) {
108+
prnfsNotificationBuilder
109+
.withFilterRegexp(find(a, predicate(AdminFormValues.FIELDS.filter_regexp.name())).get(VALUE));
110+
}
97111
return prnfsNotificationBuilder.build();
98112
}
99113

src/main/java/se/bjurr/prnfs/settings/ValidationException.java

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package se.bjurr.prnfs.settings;
22

3-
43
public class ValidationException extends Exception {
54
private static final long serialVersionUID = 2203598567281456784L;
65
private final String error;

src/main/resources/admin.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@
3131
data: JSON.stringify($form.serializeArray(), null, 2),
3232
processData: false,
3333
error: function(xhr, data, error) {
34-
$.each(xhr.responseJSON, function(field,errorString) {
35-
$(".error."+field,$form).html(errorString);
36-
$(".post",$form).html("There were errors, form not saved!");
37-
});
34+
$(".error."+xhr.responseJSON.field,$form).html(xhr.responseJSON.error);
35+
$(".post",$form).html("There were errors, form not saved!");
3836
},
3937
success: function(data, text, xhr) {
4038
getAll();

0 commit comments

Comments
 (0)