diff --git a/CHANGELOG.md b/CHANGELOG.md index a4dad44..8b680db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Changelog of Pull Request Notifier for Stash. ## 1.18 * Avoiding endless loop if user not 'System Admin' when editing configuration * Triggers can be named. To make it easier to keep track of them in large installations. +* Trigger Notification Buttons on Pull Request View + * And ${BUTTON_TRIGGER_TITLE} variable resolving to title of pressed button * Building against latest Stash version (3.11.1) using latest Atlassian Maven Plugin Suite version (6.0.3) * Adding PULL_REQUEST_URL variable. Points to the pull request view in Stash. diff --git a/README.md b/README.md index c94580b..37e3acd 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,12 @@ The Pull Request Notifier for Stash can: * Invoke any URL, or set of URL:s, when a pull request event happens. * With variables available to add necessary parameters. * HTTP POST, PUT, GET and DELETE. POST and PUT also supports rendered post content. -* Be configured to trigger on any [pull request event](https://developer.atlassian.com/static/javadoc/stash/3.10.0/api/reference/com/atlassian/stash/event/pull/package-summary.html). Including source branch change (RESCOPED_FROM) and target branch change (RESCOPED_TO). +* Be configured to trigger on any [pull request event](https://developer.atlassian.com/static/javadoc/stash/3.10.0/api/reference/com/atlassian/stash/event/pull/package-summary.html). Including extended events: + * RESCOPED_FROM, when source branch change + * RESCOPED_TO, when target branch change + * MANUAL_TRIGGER, when trigger button in pull request view is pressed * Be configured to only trigger if the pull request mathches a filter. A filter text is constructed with any combination of the variables and then a regexp is constructed to match that text. +* Add buttons to pull request view in Stash. And map those buttons to URL invocations. This can be done by setting the filter string to ${BUTTON_TRIGGER_TITLE} and the filter regexp to title of button. * Authenticate with HTTP basic authentication. * Send custom HTTP headers * Can optionally use proxy to connect @@ -34,6 +38,7 @@ The filter text as well as the URL support variables. These are: * ${PULL_REQUEST_VERSION} Example: 1 * ${PULL_REQUEST_COMMENT_TEXT} Example: A comment * ${PULL_REQUEST_ACTION} Example: OPENED +* ${BUTTON_TRIGGER_TITLE} Example: Trigger Notification * ${PULL_REQUEST_URL} Example: http://localhost:7990/projects/PROJECT_1/repos/rep_1/pull-requests/1 * ${PULL_REQUEST_USER_DISPLAY_NAME} Example: Some User * ${PULL_REQUEST_USER_EMAIL_ADDRESS} Example: some.user@stash.domain diff --git a/pom.xml b/pom.xml index 75e5745..a2a49c2 100644 --- a/pom.xml +++ b/pom.xml @@ -100,6 +100,11 @@ stash-scm-git-api provided + + com.atlassian.plugins + atlassian-plugins-webfragment + provided + javax.servlet servlet-api diff --git a/src/main/java/se/bjurr/prnfs/ManualResource.java b/src/main/java/se/bjurr/prnfs/ManualResource.java new file mode 100644 index 0000000..9c2a7d3 --- /dev/null +++ b/src/main/java/se/bjurr/prnfs/ManualResource.java @@ -0,0 +1,156 @@ +package se.bjurr.prnfs; + +import static com.atlassian.stash.user.Permission.ADMIN; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Lists.newArrayList; +import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.Response.ok; +import static javax.ws.rs.core.Response.status; +import static javax.ws.rs.core.Response.Status.OK; +import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; +import static se.bjurr.prnfs.admin.AdminFormValues.BUTTON_VISIBILITY.EVERYONE; +import static se.bjurr.prnfs.admin.AdminFormValues.BUTTON_VISIBILITY.SYSTEM_ADMIN; +import static se.bjurr.prnfs.listener.PrnfsPullRequestAction.BUTTON_TRIGGER; +import static se.bjurr.prnfs.listener.PrnfsRenderer.PrnfsVariable.BUTTON_TRIGGER_TITLE; +import static se.bjurr.prnfs.settings.SettingsStorage.getPrnfsSettings; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; + +import se.bjurr.prnfs.admin.AdminFormValues; +import se.bjurr.prnfs.admin.AdminFormValues.BUTTON_VISIBILITY; +import se.bjurr.prnfs.listener.PrnfsPullRequestAction; +import se.bjurr.prnfs.listener.PrnfsPullRequestEventListener; +import se.bjurr.prnfs.listener.PrnfsRenderer; +import se.bjurr.prnfs.listener.PrnfsRenderer.PrnfsVariable; +import se.bjurr.prnfs.settings.PrnfsButton; +import se.bjurr.prnfs.settings.PrnfsNotification; +import se.bjurr.prnfs.settings.PrnfsSettings; + +import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory; +import com.atlassian.sal.api.user.UserKey; +import com.atlassian.sal.api.user.UserManager; +import com.atlassian.stash.pull.PullRequest; +import com.atlassian.stash.pull.PullRequestService; +import com.atlassian.stash.repository.RepositoryService; +import com.atlassian.stash.server.ApplicationPropertiesService; +import com.atlassian.stash.user.SecurityService; +import com.atlassian.stash.user.StashUser; +import com.atlassian.stash.user.UserService; +import com.atlassian.stash.util.Operation; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.gson.Gson; + +@Path("/manual") +public class ManualResource { + private static Gson gson = new Gson(); + private final UserManager userManager; + private final UserService userService; + private final PullRequestService pullRequestService; + private final PrnfsPullRequestEventListener prnfsPullRequestEventListener; + private final SecurityService securityService; + private final PluginSettingsFactory pluginSettingsFactory; + private static final List adminOk = newArrayList(); + private static final List systemAdminOk = newArrayList(); + static { + adminOk.add(BUTTON_VISIBILITY.ADMIN); + adminOk.add(SYSTEM_ADMIN); + systemAdminOk.add(SYSTEM_ADMIN); + } + + public ManualResource(UserManager userManager, UserService userService, PluginSettingsFactory pluginSettingsFactory, + PullRequestService pullRequestService, PrnfsPullRequestEventListener prnfsPullRequestEventListener, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, SecurityService securityService) { + this.userManager = userManager; + this.userService = userService; + this.pullRequestService = pullRequestService; + this.prnfsPullRequestEventListener = prnfsPullRequestEventListener; + this.securityService = securityService; + this.pluginSettingsFactory = pluginSettingsFactory; + } + + @GET + @Produces(APPLICATION_JSON) + public Response get(@Context HttpServletRequest request) throws Exception { + if (userManager.getRemoteUser(request) == null) { + return status(UNAUTHORIZED).build(); + } + List buttons = newArrayList(); + for (PrnfsButton candidate : getSettings().getButtons()) { + UserKey userKey = userManager.getRemoteUserKey(); + if (canUseButton(candidate, userManager.isAdmin(userKey), userManager.isSystemAdmin(userKey))) { + buttons.add(candidate); + } + } + return ok(gson.toJson(buttons), APPLICATION_JSON).build(); + } + + static boolean canUseButton(PrnfsButton candidate, boolean isAdmin, boolean isSystemAdmin) { + if (candidate.getVisibility().equals(EVERYONE)) { + return TRUE; + } + if (isSystemAdmin && systemAdminOk.contains(candidate.getVisibility())) { + return TRUE; + } else if (isAdmin && adminOk.contains(candidate.getVisibility())) { + return TRUE; + } else if (candidate.getVisibility().equals(EVERYONE)) { + return TRUE; + } + return FALSE; + } + + @POST + @Produces(APPLICATION_JSON) + public Response post(@Context HttpServletRequest request, @QueryParam("repositoryId") Integer repositoryId, + @QueryParam("pullRequestId") Long pullRequestId, @QueryParam("formIdentifier") final String formIdentifier) + throws Exception { + if (userManager.getRemoteUser(request) == null) { + return status(UNAUTHORIZED).build(); + } + + final PullRequest pullRequest = pullRequestService.getById(repositoryId, pullRequestId); + final PrnfsSettings settings = getSettings(); + for (PrnfsNotification prnfsNotification : settings.getNotifications()) { + PrnfsPullRequestAction pullRequestAction = PrnfsPullRequestAction.valueOf(BUTTON_TRIGGER); + StashUser stashUser = userService.getUserBySlug(userManager.getRemoteUser(request).getUsername()); + Map> variables = new HashMap>(); + variables.put(BUTTON_TRIGGER_TITLE, new Supplier() { + @Override + public String get() { + return find(settings.getButtons(), new Predicate() { + @Override + public boolean apply(PrnfsButton input) { + return input.getFormIdentifier().equals(formIdentifier); + } + }).getTitle(); + } + }); + prnfsPullRequestEventListener.notify(prnfsNotification, pullRequestAction, pullRequest, stashUser, variables); + } + return status(OK).build(); + } + + private PrnfsSettings getSettings() throws Exception { + final PrnfsSettings settings = securityService.withPermission(ADMIN, "Getting config").call( + new Operation() { + @Override + public PrnfsSettings perform() throws Exception { + return getPrnfsSettings(pluginSettingsFactory.createGlobalSettings()); + } + }); + return settings; + } +} \ No newline at end of file diff --git a/src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java b/src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java index dd08ca2..5c6653c 100644 --- a/src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java +++ b/src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java @@ -16,7 +16,15 @@ public final class AdminFormValues extends ArrayList> { public static final String DEFAULT_NAME = "Unnamed trigger"; + public enum FORM_TYPE { + BUTTON_CONFIG_FORM, TRIGGER_CONFIG_FORM + }; + + public enum BUTTON_VISIBILITY { + NONE, SYSTEM_ADMIN, ADMIN, EVERYONE + }; + public enum FIELDS { - user, password, events, FORM_IDENTIFIER, url, filter_string, filter_regexp, method, post_content, proxy_user, proxy_password, proxy_server, proxy_port, header_name, header_value, name + user, password, events, FORM_IDENTIFIER, FORM_TYPE, url, filter_string, filter_regexp, method, post_content, proxy_user, proxy_password, proxy_server, proxy_port, header_name, header_value, name, button_title, button_visibility } } diff --git a/src/main/java/se/bjurr/prnfs/admin/ConfigResource.java b/src/main/java/se/bjurr/prnfs/admin/ConfigResource.java index f9f6efb..d12a69a 100644 --- a/src/main/java/se/bjurr/prnfs/admin/ConfigResource.java +++ b/src/main/java/se/bjurr/prnfs/admin/ConfigResource.java @@ -6,9 +6,13 @@ import static javax.ws.rs.core.Response.status; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; +import static se.bjurr.prnfs.settings.PrnfsNotification.isOfType; +import static se.bjurr.prnfs.settings.SettingsStorage.checkFieldsRecognized; import static se.bjurr.prnfs.settings.SettingsStorage.deleteSettings; +import static se.bjurr.prnfs.settings.SettingsStorage.getPrnfsButton; import static se.bjurr.prnfs.settings.SettingsStorage.getPrnfsNotification; import static se.bjurr.prnfs.settings.SettingsStorage.getSettingsAsFormValues; +import static se.bjurr.prnfs.settings.SettingsStorage.injectFormIdentifierIfNotSet; import static se.bjurr.prnfs.settings.SettingsStorage.storeSettings; import javax.servlet.http.HttpServletRequest; @@ -50,7 +54,7 @@ public ConfigResource(UserManager userManager, PluginSettingsFactory pluginSetti @DELETE @Path("{id}") public Response delete(@PathParam("id") final String id, @Context HttpServletRequest request) { - if (!isAdminLoggedIn(request)) { + if (!isSystemAdminLoggedIn(request)) { return status(UNAUTHORIZED).build(); } @@ -70,7 +74,7 @@ public Object doInTransaction() { @GET @Produces(APPLICATION_JSON) public Response get(@Context HttpServletRequest request) { - if (!isAdminLoggedIn(request)) { + if (!isSystemAdminLoggedIn(request)) { return status(UNAUTHORIZED).build(); } @@ -94,7 +98,7 @@ public UserManager getUserManager() { return userManager; } - private boolean isAdminLoggedIn(HttpServletRequest request) { + private boolean isSystemAdminLoggedIn(HttpServletRequest request) { final UserProfile user = userManager.getRemoteUser(request); if (user == null) { return false; @@ -109,7 +113,7 @@ private boolean isAdminLoggedIn(HttpServletRequest request) { @Consumes(APPLICATION_JSON) @Produces(APPLICATION_JSON) public Response post(final AdminFormValues config, @Context HttpServletRequest request) { - if (!isAdminLoggedIn(request)) { + if (!isSystemAdminLoggedIn(request)) { return status(UNAUTHORIZED).build(); } @@ -117,7 +121,15 @@ public Response post(final AdminFormValues config, @Context HttpServletRequest r * Validate */ try { - getPrnfsNotification(config); + injectFormIdentifierIfNotSet(config); + checkFieldsRecognized(config); + if (isOfType(config, AdminFormValues.FORM_TYPE.TRIGGER_CONFIG_FORM)) { + // Assuming TRIGGER_CONFIG_FORM here if field not available, to be backwards + // compatible + getPrnfsNotification(config); + } else { + getPrnfsButton(config); + } } catch (final ValidationException e) { return status(BAD_REQUEST).entity(new AdminFormError(e.getField(), e.getError())).build(); } diff --git a/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestAction.java b/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestAction.java index 6690ad5..49494d3 100644 --- a/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestAction.java +++ b/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestAction.java @@ -26,6 +26,8 @@ public class PrnfsPullRequestAction { public static final String RESCOPED_FROM = "RESCOPED_FROM"; + public static final String BUTTON_TRIGGER = "BUTTON_TRIGGER"; + private static final Map values = new ImmutableMap.Builder() .put(APPROVED.name(), new PrnfsPullRequestAction(APPROVED.name())) // .put(COMMENTED.name(), new PrnfsPullRequestAction(COMMENTED.name())) // @@ -38,6 +40,7 @@ public class PrnfsPullRequestAction { .put(RESCOPED_TO, new PrnfsPullRequestAction(RESCOPED_TO)) // .put(UNAPPROVED.name(), new PrnfsPullRequestAction(UNAPPROVED.name())) // .put(UPDATED.name(), new PrnfsPullRequestAction(UPDATED.name())) // + .put(BUTTON_TRIGGER, new PrnfsPullRequestAction(BUTTON_TRIGGER)) // .build(); private final String name; diff --git a/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java b/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java index d02d4c9..69b736e 100644 --- a/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java +++ b/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java @@ -6,12 +6,17 @@ import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION; import static javax.xml.bind.DatatypeConverter.printBase64Binary; import static se.bjurr.prnfs.listener.PrnfsPullRequestAction.fromPullRequestEvent; +import static se.bjurr.prnfs.listener.PrnfsRenderer.PrnfsVariable.PULL_REQUEST_COMMENT_TEXT; import static se.bjurr.prnfs.listener.UrlInvoker.urlInvoker; import static se.bjurr.prnfs.settings.SettingsStorage.getPrnfsSettings; +import java.util.HashMap; +import java.util.Map; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import se.bjurr.prnfs.listener.PrnfsRenderer.PrnfsVariable; import se.bjurr.prnfs.settings.Header; import se.bjurr.prnfs.settings.PrnfsNotification; import se.bjurr.prnfs.settings.PrnfsSettings; @@ -33,8 +38,10 @@ import com.atlassian.stash.pull.PullRequest; import com.atlassian.stash.repository.RepositoryService; import com.atlassian.stash.server.ApplicationPropertiesService; +import com.atlassian.stash.user.StashUser; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; +import com.google.common.base.Supplier; public class PrnfsPullRequestEventListener { @@ -117,52 +124,68 @@ public void onEvent(PullRequestUpdatedEvent e) { } @VisibleForTesting - public void handleEvent(PullRequestEvent pullRequestEvent) { + public void handleEvent(final PullRequestEvent pullRequestEvent) { try { if (pullRequestEvent.getPullRequest().isClosed()) { return; } final PrnfsSettings settings = getPrnfsSettings(pluginSettingsFactory.createGlobalSettings()); for (final PrnfsNotification notification : settings.getNotifications()) { - final PrnfsRenderer renderer = new PrnfsRenderer(pullRequestEvent, repositoryService, propertiesService, - notification); PrnfsPullRequestAction action = fromPullRequestEvent(pullRequestEvent, notification); - PullRequest pr = pullRequestEvent.getPullRequest(); - if (notification.getFilterRegexp().isPresent() - && notification.getFilterString().isPresent() - && !compile(notification.getFilterRegexp().get()).matcher(renderer.render(notification.getFilterString().get())) - .find()) { - continue; - } - if (notification.getTriggers().contains(action)) { - Optional postContent = absent(); - if (notification.getPostContent().isPresent()) { - postContent = Optional.of(renderer.render(notification.getPostContent().get())); - } - String renderedUrl = renderer.render(notification.getUrl()); - logger.info(notification.getName() + " > " + action.getName() + " "// - + pr.getFromRef().getId() + "(" + pr.getFromRef().getLatestChangeset() + ") -> " // - + pr.getToRef().getId() + "(" + pr.getToRef().getLatestChangeset() + ")" + " " // - + renderedUrl); - UrlInvoker urlInvoker = urlInvoker().withUrlParam(renderedUrl).withMethod(notification.getMethod()) - .withPostContent(postContent); - if (notification.getUser().isPresent() && notification.getPassword().isPresent()) { - final String userpass = notification.getUser().get() + ":" + notification.getPassword().get(); - final String basicAuth = "Basic " + new String(printBase64Binary(userpass.getBytes(UTF_8))); - urlInvoker.withHeader(AUTHORIZATION, basicAuth); - } - for (Header header : notification.getHeaders()) { - urlInvoker.withHeader(header.getName(), renderer.render(header.getValue())); - } - urlInvoker.withProxyServer(notification.getProxyServer()); - urlInvoker.withProxyPort(notification.getProxyPort()); - urlInvoker.withProxyUser(notification.getProxyUser()); - urlInvoker.withProxyPassword(notification.getProxyPassword()); - invoker.invoke(urlInvoker); + HashMap> variables = new HashMap>(); + if (pullRequestEvent instanceof PullRequestCommentAddedEvent) { + variables.put(PULL_REQUEST_COMMENT_TEXT, new Supplier() { + @Override + public String get() { + return ((PullRequestCommentAddedEvent) pullRequestEvent).getComment().getText(); + } + }); } + PullRequest pr = pullRequestEvent.getPullRequest(); + notify(notification, action, pr, pullRequestEvent.getUser(), variables); } } catch (final ValidationException e) { logger.error("", e); } } + + @SuppressWarnings("deprecation") + public void notify(final PrnfsNotification notification, PrnfsPullRequestAction pullRequestAction, + PullRequest pullRequest, StashUser stashUser, Map> variables) { + PrnfsRenderer renderer = new PrnfsRenderer(pullRequest, pullRequestAction, stashUser, repositoryService, + propertiesService, notification, variables); + if (!notification.getTriggers().contains(pullRequestAction)) { + return; + } + if (notification.getFilterRegexp().isPresent() + && notification.getFilterString().isPresent() + && !compile(notification.getFilterRegexp().get()).matcher(renderer.render(notification.getFilterString().get())) + .find()) { + return; + } + Optional postContent = absent(); + if (notification.getPostContent().isPresent()) { + postContent = Optional.of(renderer.render(notification.getPostContent().get())); + } + String renderedUrl = renderer.render(notification.getUrl()); + logger.info(notification.getName() + " > " // + + pullRequest.getFromRef().getId() + "(" + pullRequest.getFromRef().getLatestChangeset() + ") -> " // + + pullRequest.getToRef().getId() + "(" + pullRequest.getToRef().getLatestChangeset() + ")" + " " // + + renderedUrl); + UrlInvoker urlInvoker = urlInvoker().withUrlParam(renderedUrl).withMethod(notification.getMethod()) + .withPostContent(postContent); + if (notification.getUser().isPresent() && notification.getPassword().isPresent()) { + final String userpass = notification.getUser().get() + ":" + notification.getPassword().get(); + final String basicAuth = "Basic " + new String(printBase64Binary(userpass.getBytes(UTF_8))); + urlInvoker.withHeader(AUTHORIZATION, basicAuth); + } + for (Header header : notification.getHeaders()) { + urlInvoker.withHeader(header.getName(), renderer.render(header.getValue())); + } + urlInvoker.withProxyServer(notification.getProxyServer()); + urlInvoker.withProxyPort(notification.getProxyPort()); + urlInvoker.withProxyUser(notification.getProxyUser()); + urlInvoker.withProxyPassword(notification.getProxyPassword()); + invoker.invoke(urlInvoker); + } } \ No newline at end of file diff --git a/src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java b/src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java index fafa33d..c5b44ba 100644 --- a/src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java +++ b/src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java @@ -1,21 +1,21 @@ package se.bjurr.prnfs.listener; -import static se.bjurr.prnfs.listener.PrnfsPullRequestAction.fromPullRequestEvent; import static se.bjurr.prnfs.listener.PrnfsRenderer.REPO_PROTOCOL.http; import static se.bjurr.prnfs.listener.PrnfsRenderer.REPO_PROTOCOL.ssh; +import java.util.Map; import java.util.Set; import se.bjurr.prnfs.settings.PrnfsNotification; -import com.atlassian.stash.event.pull.PullRequestCommentAddedEvent; -import com.atlassian.stash.event.pull.PullRequestEvent; import com.atlassian.stash.pull.PullRequest; import com.atlassian.stash.repository.Repository; import com.atlassian.stash.repository.RepositoryCloneLinksRequest; import com.atlassian.stash.repository.RepositoryService; import com.atlassian.stash.server.ApplicationPropertiesService; +import com.atlassian.stash.user.StashUser; import com.atlassian.stash.util.NamedLink; +import com.google.common.base.Supplier; public class PrnfsRenderer { @@ -27,219 +27,255 @@ public enum PrnfsVariable { PULL_REQUEST_FROM_HASH(new Resolver() { @SuppressWarnings("deprecation") @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getLatestChangeset(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getFromRef().getLatestChangeset(); } }), PULL_REQUEST_FROM_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getId(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getFromRef().getId(); } }), PULL_REQUEST_FROM_BRANCH(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getDisplayId(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getFromRef().getDisplayId(); } }), PULL_REQUEST_FROM_REPO_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getFromRef().getRepository().getId() + ""; } }), PULL_REQUEST_FROM_REPO_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getName() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getFromRef().getRepository().getName() + ""; } }), PULL_REQUEST_FROM_REPO_PROJECT_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getProject().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getFromRef().getRepository().getProject().getId() + ""; } }), PULL_REQUEST_FROM_REPO_PROJECT_KEY(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getProject().getKey(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getFromRef().getRepository().getProject().getKey(); } }), PULL_REQUEST_FROM_REPO_SLUG(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getSlug() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getFromRef().getRepository().getSlug() + ""; } }), PULL_REQUEST_FROM_SSH_CLONE_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return cloneUrlFromRepository(ssh, pullRequestEvent.getPullRequest().getFromRef().getRepository(), - repositoryService); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return cloneUrlFromRepository(ssh, pullRequest.getFromRef().getRepository(), repositoryService); } }), PULL_REQUEST_FROM_HTTP_CLONE_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return cloneUrlFromRepository(http, pullRequestEvent.getPullRequest().getFromRef().getRepository(), - repositoryService); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return cloneUrlFromRepository(http, pullRequest.getFromRef().getRepository(), repositoryService); } }), PULL_REQUEST_ACTION(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return fromPullRequestEvent(pullRequestEvent, prnfsNotification).getName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return prnfsPullRequestAction.getName(); } }), PULL_REQUEST_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return getPullRequestUrl(propertiesService, pullRequestEvent.getPullRequest()); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return getPullRequestUrl(propertiesService, pullRequest); } }), PULL_REQUEST_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getId() + ""; } }), PULL_REQUEST_VERSION(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getVersion() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getVersion() + ""; } }), PULL_REQUEST_AUTHOR_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getAuthor().getUser().getId() + ""; } }), PULL_REQUEST_AUTHOR_DISPLAY_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getDisplayName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getAuthor().getUser().getDisplayName(); } }), PULL_REQUEST_AUTHOR_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getAuthor().getUser().getName(); } }), PULL_REQUEST_AUTHOR_EMAIL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getEmailAddress(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getAuthor().getUser().getEmailAddress(); } }), PULL_REQUEST_AUTHOR_SLUG(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getSlug(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getAuthor().getUser().getSlug(); } }), PULL_REQUEST_TO_HASH(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getLatestChangeset(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getToRef().getLatestChangeset(); } }), PULL_REQUEST_TO_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getId(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getToRef().getId(); } }), PULL_REQUEST_TO_BRANCH(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getDisplayId(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getToRef().getDisplayId(); } }), PULL_REQUEST_TO_REPO_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getToRef().getRepository().getId() + ""; } }), PULL_REQUEST_TO_REPO_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getName() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getToRef().getRepository().getName() + ""; } }), PULL_REQUEST_TO_REPO_PROJECT_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getProject().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getToRef().getRepository().getProject().getId() + ""; } }), PULL_REQUEST_TO_REPO_PROJECT_KEY(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getProject().getKey(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getToRef().getRepository().getProject().getKey(); } }), PULL_REQUEST_TO_REPO_SLUG(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getSlug() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return pullRequest.getToRef().getRepository().getSlug() + ""; } }), PULL_REQUEST_TO_SSH_CLONE_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return cloneUrlFromRepository(ssh, pullRequestEvent.getPullRequest().getToRef().getRepository(), repositoryService); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return cloneUrlFromRepository(ssh, pullRequest.getToRef().getRepository(), repositoryService); } }), PULL_REQUEST_TO_HTTP_CLONE_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return cloneUrlFromRepository(http, pullRequestEvent.getPullRequest().getToRef().getRepository(), repositoryService); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return cloneUrlFromRepository(http, pullRequest.getToRef().getRepository(), repositoryService); } }), PULL_REQUEST_COMMENT_TEXT(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - if (pullRequestEvent instanceof PullRequestCommentAddedEvent) { - return ((PullRequestCommentAddedEvent) pullRequestEvent).getComment().getText(); - } else { - return ""; - } + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return getOrEmpty(variables, PULL_REQUEST_COMMENT_TEXT); } }), PULL_REQUEST_USER_DISPLAY_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getDisplayName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return stashUser.getDisplayName(); } }), PULL_REQUEST_USER_EMAIL_ADDRESS(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getEmailAddress(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return stashUser.getEmailAddress(); } }), PULL_REQUEST_USER_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return stashUser.getId() + ""; } }), PULL_REQUEST_USER_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return stashUser.getName(); } }), PULL_REQUEST_USER_SLUG(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getSlug(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return stashUser.getSlug(); + } + }), BUTTON_TRIGGER_TITLE(new Resolver() { + @Override + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return getOrEmpty(variables, BUTTON_TRIGGER_TITLE); } }); @@ -262,36 +298,62 @@ private static String getPullRequestUrl(ApplicationPropertiesService propertiesS this.resolver = resolver; } - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - return resolver.resolve(pullRequestEvent, repositoryService, propertiesService, prnfsNotification); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + return resolver.resolve(pullRequest, pullRequestAction, stashUser, repositoryService, propertiesService, + prnfsNotification, variables); + } + + private static String getOrEmpty(Map> variables, PrnfsVariable variable) { + if (variables.get(variable) == null) { + return ""; + } + return variables.get(variable).get(); } } public interface Resolver { - String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification); + String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables); } - private final PullRequestEvent pullRequestEvent; private final RepositoryService repositoryService; - private final ApplicationPropertiesService propertiesService; private final PrnfsNotification prnfsNotification; + private final PullRequest pullRequest; + private final PrnfsPullRequestAction pullRequestAction; + private final StashUser stashUser; + private final ApplicationPropertiesService propertiesService; + /** + * Contains special variables that are only available for specific events like + * {@link PrnfsVariable#BUTTON_TRIGGER_TITLE} and + * {@link PrnfsVariable#PULL_REQUEST_COMMENT_TEXT}. + */ + private final Map> variables; - public PrnfsRenderer(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - ApplicationPropertiesService propertiesService, PrnfsNotification prnfsNotification) { - this.pullRequestEvent = pullRequestEvent; + /** + * @param variables + * {@link #variables} + */ + public PrnfsRenderer(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, ApplicationPropertiesService propertiesService, + PrnfsNotification prnfsNotification, Map> variables) { + this.pullRequest = pullRequest; + this.pullRequestAction = pullRequestAction; + this.stashUser = stashUser; this.repositoryService = repositoryService; - this.propertiesService = propertiesService; this.prnfsNotification = prnfsNotification; + this.propertiesService = propertiesService; + this.variables = variables; } public String render(String string) { for (final PrnfsVariable variable : PrnfsVariable.values()) { final String regExpStr = "\\$\\{" + variable.name() + "\\}"; if (string.contains(regExpStr.replaceAll("\\\\", ""))) { - string = string.replaceAll(regExpStr, - variable.resolve(pullRequestEvent, repositoryService, propertiesService, prnfsNotification)); + string = string.replaceAll(regExpStr, variable.resolve(pullRequest, pullRequestAction, stashUser, + repositoryService, propertiesService, prnfsNotification, variables)); } } return string; diff --git a/src/main/java/se/bjurr/prnfs/settings/PrnfsButton.java b/src/main/java/se/bjurr/prnfs/settings/PrnfsButton.java new file mode 100644 index 0000000..b052b28 --- /dev/null +++ b/src/main/java/se/bjurr/prnfs/settings/PrnfsButton.java @@ -0,0 +1,28 @@ +package se.bjurr.prnfs.settings; + +import se.bjurr.prnfs.admin.AdminFormValues.BUTTON_VISIBILITY; + +public class PrnfsButton { + + private final String title; + private final BUTTON_VISIBILITY visibility; + private final String formIdentifier; + + public PrnfsButton(String title, BUTTON_VISIBILITY visibility, String formIdentifier) { + this.title = title; + this.visibility = visibility; + this.formIdentifier = formIdentifier; + } + + public String getTitle() { + return title; + } + + public BUTTON_VISIBILITY getVisibility() { + return visibility; + } + + public String getFormIdentifier() { + return formIdentifier; + } +} diff --git a/src/main/java/se/bjurr/prnfs/settings/PrnfsNotification.java b/src/main/java/se/bjurr/prnfs/settings/PrnfsNotification.java index f1e9c54..7f3e00e 100644 --- a/src/main/java/se/bjurr/prnfs/settings/PrnfsNotification.java +++ b/src/main/java/se/bjurr/prnfs/settings/PrnfsNotification.java @@ -5,13 +5,18 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.emptyToNull; import static com.google.common.base.Strings.nullToEmpty; +import static com.google.common.collect.Iterables.tryFind; import static java.util.regex.Pattern.compile; import static se.bjurr.prnfs.admin.AdminFormValues.DEFAULT_NAME; +import static se.bjurr.prnfs.admin.AdminFormValues.VALUE; +import static se.bjurr.prnfs.settings.PrnfsPredicates.predicate; import java.net.URL; import java.util.List; +import java.util.Map; import se.bjurr.prnfs.admin.AdminFormValues; +import se.bjurr.prnfs.admin.AdminFormValues.FORM_TYPE; import se.bjurr.prnfs.listener.PrnfsPullRequestAction; import com.google.common.base.Optional; @@ -126,4 +131,10 @@ public Optional getPostContent() { public List
getHeaders() { return headers; } + + public static boolean isOfType(AdminFormValues config, FORM_TYPE formType) { + Optional> formTypeOpt = tryFind(config, predicate(AdminFormValues.FIELDS.FORM_TYPE.name())); + return !formTypeOpt.isPresent() && formType.name().equals(FORM_TYPE.TRIGGER_CONFIG_FORM.name()) + || formTypeOpt.get().get(VALUE).equals(AdminFormValues.FORM_TYPE.TRIGGER_CONFIG_FORM.name()); + } } diff --git a/src/main/java/se/bjurr/prnfs/settings/PrnfsSettings.java b/src/main/java/se/bjurr/prnfs/settings/PrnfsSettings.java index 9e34f85..0fd3047 100644 --- a/src/main/java/se/bjurr/prnfs/settings/PrnfsSettings.java +++ b/src/main/java/se/bjurr/prnfs/settings/PrnfsSettings.java @@ -7,12 +7,18 @@ public class PrnfsSettings { private List notifications = newArrayList(); + private final List buttons; - public PrnfsSettings(List notifications) { + public PrnfsSettings(List notifications, List buttons) { this.notifications = checkNotNull(notifications); + this.buttons = checkNotNull(buttons); } public List getNotifications() { return notifications; } + + public List getButtons() { + return buttons; + } } diff --git a/src/main/java/se/bjurr/prnfs/settings/PrnfsSettingsBuilder.java b/src/main/java/se/bjurr/prnfs/settings/PrnfsSettingsBuilder.java index d9b8f6d..4e35823 100644 --- a/src/main/java/se/bjurr/prnfs/settings/PrnfsSettingsBuilder.java +++ b/src/main/java/se/bjurr/prnfs/settings/PrnfsSettingsBuilder.java @@ -10,16 +10,29 @@ public static PrnfsSettingsBuilder prnfsSettingsBuilder() { } private final List notifications = newArrayList(); + private final List buttons = newArrayList(); private PrnfsSettingsBuilder() { } public PrnfsSettings build() { - return new PrnfsSettings(notifications); + return new PrnfsSettings(notifications, buttons); } public PrnfsSettingsBuilder withNotification(PrnfsNotification notification) { this.notifications.add(notification); return this; } + + public void withButton(PrnfsButton prnfsButton) { + this.buttons.add(prnfsButton); + } + + public List getButtons() { + return buttons; + } + + public List getNotifications() { + return notifications; + } } diff --git a/src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java b/src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java index 9f2183d..a9224c6 100644 --- a/src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java +++ b/src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java @@ -12,6 +12,7 @@ import static se.bjurr.prnfs.admin.AdminFormValues.DEFAULT_NAME; import static se.bjurr.prnfs.admin.AdminFormValues.NAME; import static se.bjurr.prnfs.admin.AdminFormValues.VALUE; +import static se.bjurr.prnfs.settings.PrnfsNotification.isOfType; import static se.bjurr.prnfs.settings.PrnfsNotificationBuilder.prnfsNotificationBuilder; import static se.bjurr.prnfs.settings.PrnfsPredicates.predicate; import static se.bjurr.prnfs.settings.PrnfsSettingsBuilder.prnfsSettingsBuilder; @@ -26,6 +27,7 @@ import org.slf4j.LoggerFactory; import se.bjurr.prnfs.admin.AdminFormValues; +import se.bjurr.prnfs.admin.AdminFormValues.BUTTON_VISIBILITY; import se.bjurr.prnfs.listener.PrnfsPullRequestAction; import com.atlassian.sal.api.pluginsettings.PluginSettings; @@ -41,7 +43,7 @@ public class SettingsStorage { private static Random random = new Random(currentTimeMillis()); - private static final String STORAGE_KEY = AdminFormValues.class.getName() + "_2"; + public static final String STORAGE_KEY = AdminFormValues.class.getName() + "_2"; public static void deleteSettings(PluginSettings pluginSettings, String id) { final Map map = getNotificationsMap(pluginSettings); @@ -77,18 +79,25 @@ private static Map getNotificationsMap(PluginSettings p return allNotificationsMap; } - public static PrnfsNotification getPrnfsNotification(AdminFormValues adminFormValues) throws ValidationException { - for (final Map m : adminFormValues) { - for (final Entry entry : m.entrySet()) { - if (entry.getKey().equals(NAME)) { - if (AdminFormValues.FIELDS.valueOf(entry.getValue()) == null) { - throw new ValidationException(entry.getValue(), "Field not recognized!"); - } - } else if (!entry.getKey().equals(VALUE)) { - throw new ValidationException(entry.getKey(), "Key not recognized!"); - } - } + public static PrnfsButton getPrnfsButton(AdminFormValues adminFormValues) throws ValidationException { + final Optional> titleOpt = tryFind(adminFormValues, + predicate(AdminFormValues.FIELDS.button_title.name())); + String title = "Trigger Notification"; + if (titleOpt.isPresent()) { + title = titleOpt.get().get(VALUE); + } + + final Optional> visibilityOpt = tryFind(adminFormValues, + predicate(AdminFormValues.FIELDS.button_visibility.name())); + BUTTON_VISIBILITY visibility = AdminFormValues.BUTTON_VISIBILITY.NONE; + if (visibilityOpt.isPresent()) { + visibility = AdminFormValues.BUTTON_VISIBILITY.valueOf(visibilityOpt.get().get(VALUE)); } + return new PrnfsButton(title, visibility, find(adminFormValues, + predicate(AdminFormValues.FIELDS.FORM_IDENTIFIER.name())).get(VALUE)); + } + + public static PrnfsNotification getPrnfsNotification(AdminFormValues adminFormValues) throws ValidationException { final Optional> urlOpt = tryFind(adminFormValues, predicate(AdminFormValues.FIELDS.url.name())); if (!urlOpt.isPresent()) { throw new ValidationException("url", "URL not set"); @@ -155,10 +164,28 @@ public static PrnfsNotification getPrnfsNotification(AdminFormValues adminFormVa return prnfsNotificationBuilder.build(); } + public static void checkFieldsRecognized(AdminFormValues adminFormValues) throws ValidationException { + for (final Map m : adminFormValues) { + for (final Entry entry : m.entrySet()) { + if (entry.getKey().equals(NAME)) { + if (AdminFormValues.FIELDS.valueOf(entry.getValue()) == null) { + throw new ValidationException(entry.getValue(), "Field not recognized!"); + } + } else if (!entry.getKey().equals(VALUE)) { + throw new ValidationException(entry.getKey(), "Key not recognized!"); + } + } + } + } + public static PrnfsSettings getPrnfsSettings(PluginSettings pluginSettings) throws ValidationException { final PrnfsSettingsBuilder prnfsSettingsBuilder = prnfsSettingsBuilder(); - for (final AdminFormValues a : getSettingsAsFormValues(pluginSettings)) { - prnfsSettingsBuilder.withNotification(getPrnfsNotification(a)); + for (final AdminFormValues adminFormValues : getSettingsAsFormValues(pluginSettings)) { + if (isOfType(adminFormValues, AdminFormValues.FORM_TYPE.TRIGGER_CONFIG_FORM)) { + prnfsSettingsBuilder.withNotification(getPrnfsNotification(adminFormValues)); + } else { + prnfsSettingsBuilder.withButton(getPrnfsButton(adminFormValues)); + } } return prnfsSettingsBuilder.build(); } @@ -216,8 +243,13 @@ private static void storeNotificationsMap(PluginSettings pluginSettings, public static void storeSettings(PluginSettings pluginSettings, final AdminFormValues config) throws ValidationException { + injectFormIdentifierIfNotSet(config); final Map allNotificationsMap = getNotificationsMap(pluginSettings); + allNotificationsMap.put(find(config, predicate(AdminFormValues.FIELDS.FORM_IDENTIFIER.name())).get(VALUE), config); + storeNotificationsMap(pluginSettings, allNotificationsMap); + } + public static void injectFormIdentifierIfNotSet(final AdminFormValues config) { final Optional> formIdOpt = tryFind(config, predicate(AdminFormValues.FIELDS.FORM_IDENTIFIER.name())); if (!formIdOpt.isPresent() || formIdOpt.get().get(VALUE).trim().isEmpty()) { @@ -226,9 +258,5 @@ public static void storeSettings(PluginSettings pluginSettings, final AdminFormV config.add(new ImmutableMap.Builder().put(NAME, AdminFormValues.FIELDS.FORM_IDENTIFIER.name()) .put(VALUE, generatedIdentifier).build()); } - - allNotificationsMap.put(find(config, predicate(AdminFormValues.FIELDS.FORM_IDENTIFIER.name())).get(VALUE), config); - - storeNotificationsMap(pluginSettings, allNotificationsMap); } } diff --git a/src/main/resources/admin.css b/src/main/resources/admin.css index b8e0dd5..a4b0403 100644 --- a/src/main/resources/admin.css +++ b/src/main/resources/admin.css @@ -1,10 +1,7 @@ -.trigger { +.config-area { border: 1px; border-color: black; border-style: dotted; -} - -.trigger { width: 400px; padding: 5px 15px; } diff --git a/src/main/resources/admin.js b/src/main/resources/admin.js index 6917cb8..e19cd12 100644 --- a/src/main/resources/admin.js +++ b/src/main/resources/admin.js @@ -1,4 +1,5 @@ (function ($) { + 'use strict'; var config_resource = AJS.contextPath() + "/rest/prnfs-admin/1.0/"; $(document).ready(function() { function getEmpties($headers) { @@ -16,8 +17,8 @@ } function adjustHeaders($headers) { - var empties = getEmpties($headers) - if (empties.length == 0) { + var empties = getEmpties($headers); + if (empties.length === 0) { $headers.append($(".prnfs-template .header")[0].outerHTML); } @@ -75,7 +76,7 @@ $(".error."+xhr.responseJSON.field,$form).html(xhr.responseJSON.error); if (xhr.responseJSON.field) { $(".post",$form).html("There were errors, form not saved!"); - } else { + } else { $(".post",$form).html(xhr.responseText); } }, @@ -85,13 +86,13 @@ }); }); } - - function addNewForm() { - var $template = $(".prnfs-template").clone(); + + function addNewForm(formType) { + var $template = $(".prnfs-template-"+formType).clone(); $('input[name="delete"]',$template).remove(); $('input[name=method][value=GET]', $template).attr('checked','checked'); $('.expandable',$template).addClass('expanded'); - $(".prnfs").append($template.html()); + $(".prnfs-"+formType).append($template.html()); } function getAll() { @@ -99,9 +100,18 @@ url: config_resource, dataType: "json" }).done(function(configs) { - $(".prnfs").html(""); + $(".prnfs-TRIGGER_CONFIG_FORM").html(""); + $(".prnfs-BUTTON_CONFIG_FORM").html(""); $.each(configs, function(index, config) { - var $template = $(".prnfs-template").clone(); + var formType = 'TRIGGER_CONFIG_FORM'; + $.each(config, function(fieldIndex,field_map) { + if (field_map.name === 'FORM_TYPE') { + formType = field_map.value; + } + }); + + var $template = $(".prnfs-template-"+formType).clone(); + $.each(config, function(fieldIndex,field_map) { $('.variable[data-variable="'+field_map.name+'"]', $template).html(field_map.value); $('input[type="text"][name="'+field_map.name+'"]', $template).attr('value', field_map.value); @@ -112,13 +122,13 @@ $('input[type="radio"][name="'+field_map.name+'"][value="'+field_map.value+'"]', $template).attr('checked','checked'); $('.visibleif.'+field_map.name+'_'+field_map.value.replace(/[^a-zA-Z]/g,''), $template).show(); }); - + var header_names = []; var header_values = []; $.each(config, function(fieldIndex,field_map) { - if (field_map.name == 'header_name') { + if (field_map.name === 'header_name') { header_names.push(field_map.value); - } else if (field_map.name == 'header_value') { + } else if (field_map.name === 'header_value') { header_values.push(field_map.value); } }); @@ -127,13 +137,15 @@ $('input[type="text"][name="header_value"]', $template).last().attr('value', header_values[i]); adjustHeaders($(".headers", $template)); } - + if (!$('input[name=method]:checked', $template).val()) { $('input[name=method][value=GET]', $template).attr('checked','checked'); } - $(".prnfs").append($template.html()); + + $(".prnfs-"+formType).append($template.html()); }); - addNewForm(); + addNewForm('TRIGGER_CONFIG_FORM'); + addNewForm('BUTTON_CONFIG_FORM'); setEvents(); }); } diff --git a/src/main/resources/admin.vm b/src/main/resources/admin.vm index 0699962..463614e 100644 --- a/src/main/resources/admin.vm +++ b/src/main/resources/admin.vm @@ -5,6 +5,10 @@ $webResourceManager.requireResource("se.bjurr.prnfs.pull-request-notifier-for-stash:resources") + +
+
+
You can use variables when invoking the URL, when forming the filter string, custom header values or in POST content. @@ -14,6 +18,7 @@
  • ${PULL_REQUEST_URL} Example: http://localhost:7990/projects/PROJECT_1/repos/rep_1/pull-requests/1
  • ${PULL_REQUEST_VERSION} Example: 1
  • ${PULL_REQUEST_COMMENT_TEXT} Example: A comment
  • +
  • ${BUTTON_TRIGGER_TITLE} Example: Trigger Notification
  • ${PULL_REQUEST_USER_DISPLAY_NAME} Example: Some User
  • ${PULL_REQUEST_USER_EMAIL_ADDRESS} Example: some.user@stash.domain
  • ${PULL_REQUEST_USER_ID} Example: 1
  • @@ -48,17 +53,54 @@
    -
    +
    +
    + +
    +
    +
    + + +
    +
    + Trigger notification -button in pull request view + + +
    +
    +
    +
    + Show button for + +
    + +
    + +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    -
    -
    +
    +