diff --git a/src/main/java/io/debezium/github/bot/JiraIssueCheck.java b/src/main/java/io/debezium/github/bot/JiraIssueCheck.java index 1fb5187..4468b33 100644 --- a/src/main/java/io/debezium/github/bot/JiraIssueCheck.java +++ b/src/main/java/io/debezium/github/bot/JiraIssueCheck.java @@ -14,6 +14,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.kohsuke.github.GHIssueComment; import org.kohsuke.github.GHPullRequest; import org.kohsuke.github.GHPullRequestCommitDetail; @@ -62,23 +63,66 @@ public void run(CheckContext context, CheckRunOutput output) throws IOException } } - // Perform checks - issuesAddressed(output, issueKeys); - // commitStartWithKey(output, commitsWithMessageNotStartingWithIssueKey); - issuesNotMentioned(output, getIssueKeysNotMentionedInTitleBody(context.pullRequest, issueKeys)); + // If at least one issue isn't found in the comments, add all issues in the output. + Set issuesNotInComments = getIssueKeysNotMentionedInComments(context.pullRequest, issueKeys); + if (deploymentConfig.isCheckAlwaysAddIssuesEnabled() || !issuesNotInComments.isEmpty()) { + issuesAddressed(output, deploymentConfig.isCheckAlwaysAddIssuesEnabled() ? issueKeys : issuesNotInComments); + } + + if (deploymentConfig.isCheckCommitStartWithKeyEnabled()) { + commitStartWithKey(output, commitsWithMessageNotStartingWithIssueKey); + } + + if (deploymentConfig.isCheckIssuesNotMentionedEnabled()) { + issuesNotMentioned(output, getIssueKeysNotMentionedInTitleBody(context.pullRequest, issueKeys)); + } } private List getIssueKeysNotMentionedInTitleBody(GHPullRequest pullRequest, Set issueKeys) { final String title = pullRequest.getTitle(); final String body = pullRequest.getBody(); return issueKeys.stream().filter(k -> { - if (title != null && !title.contains(k)) { - return true; - } - return body != null && !body.contains(k); + boolean foundTitle = title != null && title.contains(k); + boolean foundBody = body != null && body.contains(k); + return !foundTitle && !foundBody; }).collect(Collectors.toList()); } + private Set getIssueKeysNotMentionedInComments(GHPullRequest pullRequest, Set issueKeys) { + final Set notMentionedKeys = new LinkedHashSet<>(); + + for (String issueKey : issueKeys) { + boolean found = false; + final String jiraUrl = getJiraUrl(issueKey); + if (pullRequest.getBody() != null && pullRequest.getBody().contains(jiraUrl)) { + continue; + } + + try { + for (GHIssueComment comment : pullRequest.listComments()) { + // Ignore comments generated by the bot + final String loginName = comment.getUser().getLogin(); + if (loginName.contains(deploymentConfig.getUserName())) { + continue; + } + if (comment.getBody().contains(jiraUrl)) { + found = true; + } + } + } + catch (IOException e) { + // If this happens, lets just add the keys to the comment + return issueKeys; + } + + if (!found) { + notMentionedKeys.add(issueKey); + } + } + + return notMentionedKeys; + } + private void issuesNotMentioned(CheckRunOutput output, List issuesNotMentioned) { CheckRunRule pullRequestRule = output.rule("All issues addressed should be included in PR title"); if (issuesNotMentioned.isEmpty()) { @@ -94,7 +138,6 @@ private void issuesNotMentioned(CheckRunOutput output, List issuesNotMen } private void commitStartWithKey(CheckRunOutput output, Set commitsWithoutIssueKeys) { - // todo: disabled for now as a GH action handles this but kept this as an example CheckRunRule commitRule = output.rule("All commit messages should start with DBZ-XXXX issue key"); if (commitsWithoutIssueKeys.isEmpty()) { commitRule.passed(); diff --git a/src/main/java/io/debezium/github/bot/PullRequestContributionHandler.java b/src/main/java/io/debezium/github/bot/PullRequestContributionHandler.java index 0a4a99c..6c55d2b 100644 --- a/src/main/java/io/debezium/github/bot/PullRequestContributionHandler.java +++ b/src/main/java/io/debezium/github/bot/PullRequestContributionHandler.java @@ -37,12 +37,6 @@ public class PullRequestContributionHandler { private static final Logger LOGGER = LoggerFactory.getLogger(PullRequestContributionHandler.class); - private static final String COMMENT_INTRO_PASSED = "Thanks for your pull request!\n\n" - + "This pull request appears to follow the contribution rules. :+1:\n"; - private static final String COMMENT_INTRO_FAILED = "Thanks for your pull request!\n\n" - + "This pull request does not follow the contribution rules. Could you please review?\n"; - private static final String COMMENT_FOOTER = "\n\n---\n\n:robot: This is an auto-generated message."; - @Inject DeploymentConfig deploymentConfig; @@ -73,26 +67,38 @@ void pullRequestEvent(@Opened @Reopened @Edited @Synchronize PullRequest payload return; } + final StringBuilder rulesOutput = new StringBuilder(); + outputs.forEach(output -> output.appendFailingRules(rulesOutput)); + // Generate the comment text - StringBuilder message = new StringBuilder(passed ? COMMENT_INTRO_PASSED : COMMENT_INTRO_FAILED); - outputs.forEach(output -> output.appendFailingRules(message)); - message.append(COMMENT_FOOTER); + StringBuilder message = new StringBuilder(passed ? getPassPreamble() : getFailPreamble()); + message.append(rulesOutput); + message.append(deploymentConfig.getFooter()); // Find the comment that should be modified by the bot; may be null if none exist. GHIssueComment existingComment = findExistingComment(pullRequest); if (!deploymentConfig.isDryRun()) { if (existingComment == null) { + if (rulesOutput.length() == 0) { + LOGGER.info("Rules generated no output, adding no message."); + return; + } // No comment found, add a new comment with the message pullRequest.comment(message.toString()); } else { // Existing comment detected, update the contents + if (rulesOutput.length() == 0) { + LOGGER.info("Rules generated no output, removing existing comment."); + existingComment.delete(); + return; + } existingComment.update(message.toString()); } } else { // In dry-mode run; while contents to the log instead - LOGGER.info("PR #{} - Added comment {}", pullRequest.getNumber(), message.toString()); + LOGGER.info("PR #{} - Added comment {}", pullRequest.getNumber(), message); } } @@ -157,4 +163,12 @@ private GHIssueComment findExistingComment(GHPullRequest pullRequest) throws IOE } return null; } + + private String getPassPreamble() { + return deploymentConfig.getPassPreamble(); + } + + private String getFailPreamble() { + return deploymentConfig.getFailPreamble(); + } } diff --git a/src/main/java/io/debezium/github/bot/config/DeploymentConfig.java b/src/main/java/io/debezium/github/bot/config/DeploymentConfig.java index d6c0fe1..1a56848 100644 --- a/src/main/java/io/debezium/github/bot/config/DeploymentConfig.java +++ b/src/main/java/io/debezium/github/bot/config/DeploymentConfig.java @@ -26,4 +26,22 @@ public interface DeploymentConfig { @WithName("issue-key-pattern") String getIssueKeyPattern(); + + @WithName("check-always-add-issues") + boolean isCheckAlwaysAddIssuesEnabled(); + + @WithName("check-commit-start-with-key") + boolean isCheckCommitStartWithKeyEnabled(); + + @WithName("check-issues-not-mentioned") + boolean isCheckIssuesNotMentionedEnabled(); + + @WithName("intro-pass") + String getPassPreamble(); + + @WithName("intro-fail") + String getFailPreamble(); + + @WithName("footer") + String getFooter(); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b8c13e5..87e165d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -18,8 +18,17 @@ debezium-github-bot.issue-key-pattern=DBZ-\\d+ %dev.debezium-github-bot.issue-key-pattern=DBZ-\\d+ %test.debezium-github-bot.issue-key-pattern=DBZ-\\d+ +debezium-github-bot.intro-pass=Thanks for your pull request, it appears to follow the contribution rules. :+1:\n +debezium-github-bot.intro-fail=Thanks for your pull request, it does not follow the contribution rules. Could you please review?\n +debezium-github-bot.footer=\n + # Defines whether the bot is to run in dry-mode or not. # When in dry-mode, no comments are applied to GitHub but instead output is provided to the console. debezium-github-bot.dry-run=false %dev.debezium-github-bot.dry-run=false %test.debezium-github-bot.dry-run=false + +# Additional configs +debezium-github-bot.check-always-add-issues=true +debezium-github-bot.check-commit-start-with-key=false +debezium-github-bot.check-issues-not-mentioned=true \ No newline at end of file