/** * Get the url for notifying of Jenkins. Protected for testing purposes * * @param repository The repository to base the request to. * @param jenkinsBase The base URL of the Jenkins instance * @param cloneType The type used to clone the repository * @param customCloneUrl The url used for cloning the repository * @param strRef The branch ref related to the commit * @param strSha1 The commit's SHA1 hash code. * @param omitHashCode Defines whether the commit's SHA1 hash code is omitted in notification to * Jenkins. * @return The url to use for notifying Jenkins */ protected String getUrl( final Repository repository, final String jenkinsBase, final String cloneType, final String customCloneUrl, final String strRef, final String strSha1, boolean omitHashCode, boolean omitBranchName) { String cloneUrl = customCloneUrl; // Older installs won't have a cloneType value - treat as custom if (cloneType != null && !cloneType.equals("custom")) { if (cloneType.equals("http")) { cloneUrl = navBuilder.repo(repository).clone("git").buildAbsoluteWithoutUsername(); } else if (cloneType.equals("ssh")) { // The user just pushed to the repo, so must have had access cloneUrl = securityService.doWithPermission( "Retrieving SSH clone url", Permission.REPO_READ, new UncheckedOperation<String>() { @Override public String perform() { return sshCloneUrlResolver.getCloneUrl(repository); } }); } else { LOGGER.error("Unknown cloneType: {}", cloneType); throw new RuntimeException("Unknown cloneType: " + cloneType); } } StringBuilder url = new StringBuilder(); url.append(String.format(BASE_URL, jenkinsBase, urlEncode(cloneUrl))); if (strRef != null && !omitBranchName) url.append(String.format(BRANCH_URL_PARAMETER, urlEncode(strRef))); if (!omitHashCode) url.append(String.format(HASH_URL_PARAMETER, strSha1)); return url.toString(); }
@EventListener public void NotifySlackChannel(RepositoryPushEvent event) { // find out if notification is enabled for this repo Repository repository = event.getRepository(); SlackSettings slackSettings = slackSettingsService.getSlackSettings(repository); String globalHookUrl = slackGlobalSettingsService.getWebHookUrl(KEY_GLOBAL_SETTING_HOOK_URL); SettingsSelector settingsSelector = new SettingsSelector(slackSettingsService, slackGlobalSettingsService, repository); SlackSettings resolvedSlackSettings = settingsSelector.getResolvedSlackSettings(); if (resolvedSlackSettings.isSlackNotificationsEnabledForPush()) { String localHookUrl = slackSettings.getSlackWebHookUrl(); WebHookSelector hookSelector = new WebHookSelector(globalHookUrl, localHookUrl); ChannelSelector channelSelector = new ChannelSelector( slackGlobalSettingsService.getChannelName(KEY_GLOBAL_SLACK_CHANNEL_NAME), slackSettings.getSlackChannelName()); if (!hookSelector.isHookValid()) { log.error( "There is no valid configured Web hook url! Reason: " + hookSelector.getProblem()); return; } if (repository.isFork() && !resolvedSlackSettings.isSlackNotificationsEnabledForPersonal()) { // simply return silently when we don't want forks to get notifications unless they're // explicitly enabled return; } String repoName = repository.getSlug(); String projectName = repository.getProject().getKey(); String repoPath = projectName + "/" + event.getRepository().getName(); for (RefChange refChange : event.getRefChanges()) { String text; String ref = refChange.getRefId(); NavBuilder.Repo repoUrlBuilder = navBuilder.project(projectName).repo(repoName); String url = repoUrlBuilder.commits().until(refChange.getRefId()).buildAbsolute(); List<Changeset> myChanges = new LinkedList<Changeset>(); boolean isNewRef = refChange.getFromHash().equalsIgnoreCase("0000000000000000000000000000000000000000"); boolean isDeleted = refChange.getToHash().equalsIgnoreCase("0000000000000000000000000000000000000000") && refChange.getType() == RefChangeType.DELETE; if (isDeleted) { // issue#4: if type is "DELETE" and toHash is all zero then this is a branch delete if (ref.indexOf("refs/tags") >= 0) { text = String.format( "Tag `%s` deleted from repository <%s|`%s`>.", ref.replace("refs/tags/", ""), repoUrlBuilder.buildAbsolute(), repoPath); } else { text = String.format( "Branch `%s` deleted from repository <%s|`%s`>.", ref.replace("refs/heads/", ""), repoUrlBuilder.buildAbsolute(), repoPath); } } else if (isNewRef) { // issue#3 if fromHash is all zero (meaning the beginning of everything, probably), then // this push is probably // a new branch or tag, and we want only to display the latest commit, not the entire // history Changeset latestChangeSet = commitService.getChangeset(repository, refChange.getToHash()); myChanges.add(latestChangeSet); if (ref.indexOf("refs/tags") >= 0) { text = String.format( "Tag <%s|`%s`> pushed on <%s|`%s`>. See <%s|commit list>.", url, ref.replace("refs/tags/", ""), repoUrlBuilder.buildAbsolute(), repoPath, url); } else { text = String.format( "Branch <%s|`%s`> pushed on <%s|`%s`>. See <%s|commit list>.", url, ref.replace("refs/heads/", ""), repoUrlBuilder.buildAbsolute(), repoPath, url); } } else { ChangesetsBetweenRequest request = new ChangesetsBetweenRequest.Builder(repository) .exclude(refChange.getFromHash()) .include(refChange.getToHash()) .build(); Page<Changeset> changeSets = commitService.getChangesetsBetween( request, PageUtils.newRequest(0, PageRequest.MAX_PAGE_LIMIT)); myChanges.addAll(Lists.newArrayList(changeSets.getValues())); int commitCount = myChanges.size(); String commitStr = commitCount == 1 ? "commit" : "commits"; String branch = ref.replace("refs/heads/", ""); if (!branch.equals("master")) { continue; } text = String.format( "Push on <%s|`%s`> branch <%s|`%s`> by `%s <%s>` (%d %s). See <%s|commit list>.", repoUrlBuilder.buildAbsolute(), repoPath, url, branch, event.getUser() != null ? event.getUser().getDisplayName() : "unknown user", event.getUser() != null ? event.getUser().getEmailAddress() : "unknown email", commitCount, commitStr, url); } // Figure out what type of change this is: SlackPayload payload = new SlackPayload(); payload.setText(text); payload.setMrkdwn(true); switch (resolvedSlackSettings.getNotificationLevel()) { case COMPACT: compactCommitLog(event, refChange, payload, repoUrlBuilder, myChanges); break; case VERBOSE: verboseCommitLog(event, refChange, payload, repoUrlBuilder, text, myChanges); break; case MINIMAL: default: break; } // slackSettings.getSlackChannelName might be: // - empty // - comma separated list of channel names, eg: #mych1, #mych2, #mych3 if (channelSelector.getSelectedChannel().isEmpty()) { slackNotifier.SendSlackNotification(hookSelector.getSelectedHook(), gson.toJson(payload)); } else { // send message to multiple channels List<String> channels = Arrays.asList(channelSelector.getSelectedChannel().split("\\s*,\\s*")); for (String channel : channels) { payload.setChannel(channel.trim()); slackNotifier.SendSlackNotification( hookSelector.getSelectedHook(), gson.toJson(payload)); } } } } }
@EventListener public void NotifylesschatChannel(PullRequestActivityEvent event) { // find out if notification is enabled for this repo Repository repository = event.getPullRequest().getToRef().getRepository(); LesschatSettings lesschatSettings = lesschatSettingsService.getlesschatSettings(repository); String globalHookUrl = lesschatGlobalSettingsService.getWebHookUrl(KEY_GLOBAL_SETTING_HOOK_URL); SettingsSelector settingsSelector = new SettingsSelector(lesschatSettingsService, lesschatGlobalSettingsService, repository); LesschatSettings resolvedlesschatSettings = settingsSelector.getResolvedlesschatSettings(); if (resolvedlesschatSettings.islesschatNotificationsEnabled()) { String localHookUrl = resolvedlesschatSettings.getlesschatWebHookUrl(); WebHookSelector hookSelector = new WebHookSelector(globalHookUrl, localHookUrl); ChannelSelector channelSelector = new ChannelSelector( lesschatGlobalSettingsService.getChannelName(KEY_GLOBAL_lesschat_CHANNEL_NAME), lesschatSettings.getlesschatChannelName()); if (!hookSelector.isHookValid()) { log.error( "There is no valid configured Web hook url! Reason: " + hookSelector.getProblem()); return; } String repoName = repository.getSlug(); String projectName = repository.getProject().getKey(); long pullRequestId = event.getPullRequest().getId(); String userName = event.getUser() != null ? event.getUser().getDisplayName() : "unknown user"; String activity = event.getActivity().getAction().name(); String avatar = event.getUser() != null ? avatarService.getUrlForPerson(event.getUser(), avatarRequest) : ""; NotificationLevel resolvedLevel = resolvedlesschatSettings.getNotificationPrLevel(); // Ignore RESCOPED PR events if (activity.equalsIgnoreCase("RESCOPED") && event instanceof PullRequestRescopeActivityEvent) { return; } if (activity.equalsIgnoreCase("OPENED") && !resolvedlesschatSettings.islesschatNotificationsOpenedEnabled()) { return; } if (activity.equalsIgnoreCase("REOPENED") && !resolvedlesschatSettings.islesschatNotificationsReopenedEnabled()) { return; } if (activity.equalsIgnoreCase("UPDATED") && !resolvedlesschatSettings.islesschatNotificationsUpdatedEnabled()) { return; } if (activity.equalsIgnoreCase("APPROVED") && !resolvedlesschatSettings.islesschatNotificationsApprovedEnabled()) { return; } if (activity.equalsIgnoreCase("UNAPPROVED") && !resolvedlesschatSettings.islesschatNotificationsUnapprovedEnabled()) { return; } if (activity.equalsIgnoreCase("DECLINED") && !resolvedlesschatSettings.islesschatNotificationsDeclinedEnabled()) { return; } if (activity.equalsIgnoreCase("MERGED") && !resolvedlesschatSettings.islesschatNotificationsMergedEnabled()) { return; } if (activity.equalsIgnoreCase("COMMENTED") && !resolvedlesschatSettings.islesschatNotificationsCommentedEnabled()) { return; } String url = navBuilder .project(projectName) .repo(repoName) .pullRequest(pullRequestId) .overview() .buildAbsolute(); LesschatPayload payload = new LesschatPayload(); payload.setMrkdwn(true); payload.setLinkNames(true); LesschatAttachment attachment = new LesschatAttachment(); attachment.setAuthorName(userName); attachment.setAuthorIcon(avatar); String color = ""; String fallback = ""; String text = ""; switch (event.getActivity().getAction()) { case OPENED: attachment.setColor(ColorCode.BLUE.getCode()); attachment.setFallback( String.format( "%s opened pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); attachment.setText( String.format( "opened pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); if (resolvedLevel == NotificationLevel.COMPACT) { this.addField(attachment, "Description", event.getPullRequest().getDescription()); } if (resolvedLevel == NotificationLevel.VERBOSE) { this.addReviewers(attachment, event.getPullRequest().getReviewers()); } break; case REOPENED: attachment.setColor(ColorCode.BLUE.getCode()); attachment.setFallback( String.format( "%s reopened pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); attachment.setText( String.format( "reopened pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); if (resolvedLevel == NotificationLevel.COMPACT) { this.addField(attachment, "Description", event.getPullRequest().getDescription()); } if (resolvedLevel == NotificationLevel.VERBOSE) { this.addReviewers(attachment, event.getPullRequest().getReviewers()); } break; case UPDATED: attachment.setColor(ColorCode.PURPLE.getCode()); attachment.setFallback( String.format( "%s updated pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); attachment.setText( String.format( "updated pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); if (resolvedLevel == NotificationLevel.COMPACT) { this.addField(attachment, "Description", event.getPullRequest().getDescription()); } if (resolvedLevel == NotificationLevel.VERBOSE) { this.addReviewers(attachment, event.getPullRequest().getReviewers()); } break; case APPROVED: attachment.setColor(ColorCode.GREEN.getCode()); attachment.setFallback( String.format( "%s approved pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); attachment.setText( String.format( "approved pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); break; case UNAPPROVED: attachment.setColor(ColorCode.RED.getCode()); attachment.setFallback( String.format( "%s unapproved pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); attachment.setText( String.format( "unapproved pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); break; case DECLINED: attachment.setColor(ColorCode.RED.getCode()); attachment.setFallback( String.format( "%s declined pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); attachment.setText( String.format( "declined pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); break; case MERGED: attachment.setColor(ColorCode.GREEN.getCode()); attachment.setFallback( String.format( "%s merged pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); attachment.setText( String.format( "merged pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); break; case RESCOPED: attachment.setColor(ColorCode.PURPLE.getCode()); attachment.setFallback( String.format( "%s rescoped on pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); attachment.setText( String.format( "rescoped on pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); break; case COMMENTED: attachment.setColor(ColorCode.PALE_BLUE.getCode()); attachment.setFallback( String.format( "%s commented on pull request \"%s\". <%s|(open)>", userName, event.getPullRequest().getTitle(), url)); if (resolvedLevel == NotificationLevel.MINIMAL) { attachment.setText( String.format( "commented on pull request <%s|#%d: %s>", url, event.getPullRequest().getId(), event.getPullRequest().getTitle())); } if (resolvedLevel == NotificationLevel.COMPACT || resolvedLevel == NotificationLevel.VERBOSE) { attachment.setText( String.format( "commented on pull request <%s|#%d: %s>\n%s", url, event.getPullRequest().getId(), event.getPullRequest().getTitle(), ((PullRequestCommentActivityEvent) event) .getActivity() .getComment() .getText())); } break; } if (resolvedLevel == NotificationLevel.VERBOSE) { LesschatAttachmentField projectField = new LesschatAttachmentField(); projectField.setTitle("Source"); projectField.setValue( String.format( "_%s — %s_\n`%s`", event.getPullRequest().getFromRef().getRepository().getProject().getName(), event.getPullRequest().getFromRef().getRepository().getName(), event.getPullRequest().getFromRef().getDisplayId())); projectField.setShort(true); attachment.addField(projectField); LesschatAttachmentField repoField = new LesschatAttachmentField(); repoField.setTitle("Destination"); repoField.setValue( String.format( "_%s — %s_\n`%s`", event.getPullRequest().getFromRef().getRepository().getProject().getName(), event.getPullRequest().getToRef().getRepository().getName(), event.getPullRequest().getToRef().getDisplayId())); repoField.setShort(true); attachment.addField(repoField); } payload.addAttachment(attachment); // lesschatSettings.getlesschatChannelName might be: // - empty // - comma separated list of channel names, eg: #mych1, #mych2, #mych3 // if (channelSelector.getSelectedChannel().isEmpty()) { lesschatNotifier.SendlesschatNotification( hookSelector.getSelectedHook(), gson.toJson(payload)); // } else { // // send message to multiple channels // List<String> channels = // Arrays.asList(channelSelector.getSelectedChannel().split("\\s*,\\s*")); // for (String channel: channels) { // payload.setChannel(channel.trim()); // // lesschatNotifier.SendlesschatNotification(hookSelector.getSelectedHook(), // gson.toJson(payload)); // } // } } }