diff options
7 files changed, 95 insertions, 29 deletions
@@ -37,6 +37,19 @@ Creating a Job - Write RepositoryName - Save to preserve your changes +Merge the Pull Request's Source Branch into the Target Branch Before Building +============================================================================== +You may want Jenkins to attempt to merge your PR before doing the build -- this way it will find conflicts for you automatically. +- Follow the steps above in "Creating a Job" +- In the "Source Code Management" > "Git" > "Additional Behaviors" section, click "Add" > "Merge Before Building" +- In "Name of Repository" put "origin" (or, if not using default name, use your remote repository's name. Note: unlike in the main part of the Git Repository config, you cannot leave this item blank for "default".) +- In "Branch to merge to" put "${targetBranch}" +- Note that as long as you don't push these changes to your remote repository, the merge only happens in your local repository. + + +If you are merging into your target branch, you might want Jenkins to do a new build of the Pull Request when the target branch changes. +- There is a checkbox that says, "Rebuild if destination branch changes?" which enables this check. + Rerun test builds ==================== diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java index 65777a3..e5b0fa7 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java @@ -28,6 +28,8 @@ public class BitbucketBuildTrigger extends Trigger<AbstractProject<?, ?>> { private final String repositoryOwner; private final String repositoryName; private final String ciSkipPhrases; + private final boolean checkDestinationCommit; + transient private BitbucketPullRequestsBuilder bitbucketPullRequestsBuilder; @Extension @@ -41,7 +43,9 @@ public class BitbucketBuildTrigger extends Trigger<AbstractProject<?, ?>> { String password, String repositoryOwner, String repositoryName, - String ciSkipPhrases) throws ANTLRException { + String ciSkipPhrases, + boolean checkDestinationCommit + ) throws ANTLRException { super(cron); this.projectPath = projectPath; this.cron = cron; @@ -50,6 +54,7 @@ public class BitbucketBuildTrigger extends Trigger<AbstractProject<?, ?>> { this.repositoryOwner = repositoryOwner; this.repositoryName = repositoryName; this.ciSkipPhrases = ciSkipPhrases; + this.checkDestinationCommit = checkDestinationCommit; } public String getProjectPath() { @@ -79,6 +84,10 @@ public class BitbucketBuildTrigger extends Trigger<AbstractProject<?, ?>> { public String getCiSkipPhrases() { return ciSkipPhrases; } + + public boolean getCheckDestinationCommit() { + return checkDestinationCommit; + } @Override public void start(AbstractProject<?, ?> project, boolean newInstance) { @@ -108,7 +117,7 @@ public class BitbucketBuildTrigger extends Trigger<AbstractProject<?, ?>> { values.put("sourceBranch", new StringParameterValue("sourceBranch", cause.getSourceBranch())); values.put("targetBranch", new StringParameterValue("targetBranch", cause.getTargetBranch())); values.put("repositoryOwner", new StringParameterValue("repositoryOwner", cause.getRepositoryOwner())); - values.put("repositonyName", new StringParameterValue("repositoryName", cause.getRepositoryName())); + values.put("repositoryName", new StringParameterValue("repositoryName", cause.getRepositoryName())); values.put("pullRequestId", new StringParameterValue("pullRequestId", cause.getPullRequestId())); values.put("destinationRepositoryOwner", new StringParameterValue("destinationRepositoryOwner", cause.getDestinationRepositoryOwner())); values.put("destinationRepositoryName", new StringParameterValue("destinationRepositoryName", cause.getDestinationRepositoryName())); diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuilds.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuilds.java index 9600e26..0fa2fd0 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuilds.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuilds.java @@ -57,6 +57,6 @@ public class BitbucketBuilds { buildUrl = rootUrl + build.getUrl(); } repository.deletePullRequestComment(cause.getPullRequestId(), cause.getBuildStartCommentId()); - repository.postFinishedComment(cause.getPullRequestId(), cause.getCommitHash(), result == Result.SUCCESS, buildUrl); + repository.postFinishedComment(cause.getPullRequestId(), cause.getSourceCommitHash(), cause.getDestinationCommitHash(), result == Result.SUCCESS, buildUrl); } } diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketCause.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketCause.java index 2bdc558..4745f15 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketCause.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketCause.java @@ -14,7 +14,8 @@ public class BitbucketCause extends Cause { private final String destinationRepositoryOwner; private final String destinationRepositoryName; private final String pullRequestTitle; - private final String commitHash; + private final String sourceCommitHash; + private final String destinationCommitHash; private final String buildStartCommentId; public static final String BITBUCKET_URL = "https://bitbucket.org/"; @@ -26,7 +27,8 @@ public class BitbucketCause extends Cause { String destinationRepositoryOwner, String destinationRepositoryName, String pullRequestTitle, - String commitHash, + String sourceCommitHash, + String destinationCommitHash, String buildStartCommentId) { this.sourceBranch = sourceBranch; this.targetBranch = targetBranch; @@ -36,7 +38,8 @@ public class BitbucketCause extends Cause { this.destinationRepositoryOwner = destinationRepositoryOwner; this.destinationRepositoryName = destinationRepositoryName; this.pullRequestTitle = pullRequestTitle; - this.commitHash = commitHash; + this.sourceCommitHash = sourceCommitHash; + this.destinationCommitHash = destinationCommitHash; this.buildStartCommentId = buildStartCommentId; } @@ -72,7 +75,9 @@ public class BitbucketCause extends Cause { return pullRequestTitle; } - public String getCommitHash() { return commitHash; } + public String getSourceCommitHash() { return sourceCommitHash; } + + public String getDestinationCommitHash() { return destinationCommitHash; } public String getBuildStartCommentId() { return buildStartCommentId; } diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java index 61d3702..60e95f8 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java @@ -1,23 +1,29 @@ package bitbucketpullrequestbuilder.bitbucketpullrequestbuilder; -import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketApiClient; -import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestComment; -import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestResponseValue; -import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestResponseValueRepository; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketApiClient; +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestComment; +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestResponseValue; +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.bitbucket.BitbucketPullRequestResponseValueRepository; /** * Created by nishio */ public class BitbucketRepository { private static final Logger logger = Logger.getLogger(BitbucketRepository.class.getName()); - public static final String BUILD_START_MARKER = "[*BuildStarted*] %s"; - public static final String BUILD_FINISH_MARKER = "[*BuildFinished*] %s"; + public static final String BUILD_START_MARKER = "[*BuildStarted*] %s into %s"; + public static final String BUILD_FINISH_MARKER = "[*BuildFinished*] %s into %s"; + + public static final String BUILD_START_REGEX = "\\[\\*BuildStarted\\*\\] ([0-9a-fA-F]+) into ([0-9a-fA-F]+)"; + public static final String BUILD_FINISH_REGEX = "\\[\\*BuildFinished\\*\\] ([0-9a-fA-F]+) into ([0-9a-fA-F]+)"; + public static final String BUILD_FINISH_SENTENCE = BUILD_FINISH_MARKER + " \n\n **%s** - %s"; public static final String BUILD_REQUEST_MARKER = "test this please"; @@ -55,8 +61,9 @@ public class BitbucketRepository { } public String postBuildStartCommentTo(BitbucketPullRequestResponseValue pullRequest) { - String commit = pullRequest.getSource().getCommit().getHash(); - String comment = String.format(BUILD_START_MARKER, commit); + String sourceCommit = pullRequest.getSource().getCommit().getHash(); + String destinationCommit = pullRequest.getDestination().getCommit().getHash(); + String comment = String.format(BUILD_START_MARKER, sourceCommit, destinationCommit); BitbucketPullRequestComment commentResponse = this.client.postPullRequestComment(pullRequest.getId(), comment); return commentResponse.getCommentId().toString(); } @@ -74,6 +81,7 @@ public class BitbucketRepository { pullRequest.getDestination().getRepository().getRepositoryName(), pullRequest.getTitle(), pullRequest.getSource().getCommit().getHash(), + pullRequest.getDestination().getCommit().getHash(), commentId); this.builder.getTrigger().startJob(cause); } @@ -83,46 +91,74 @@ public class BitbucketRepository { this.client.deletePullRequestComment(pullRequestId,commentId); } - public void postFinishedComment(String pullRequestId, String commit, boolean success, String buildUrl) { + public void postFinishedComment(String pullRequestId, String sourceCommit, String destinationCommit, boolean success, String buildUrl) { String message = BUILD_FAILURE_COMMENT; if (success){ message = BUILD_SUCCESS_COMMENT; } - String comment = String.format(BUILD_FINISH_SENTENCE, commit, message, buildUrl); + String comment = String.format(BUILD_FINISH_SENTENCE, sourceCommit, destinationCommit, message, buildUrl); this.client.postPullRequestComment(pullRequestId, comment); } private boolean isBuildTarget(BitbucketPullRequestResponseValue pullRequest) { + boolean shouldBuild = true; if (pullRequest.getState() != null && pullRequest.getState().equals("OPEN")) { if (isSkipBuild(pullRequest.getTitle())) { return false; } - String commit = pullRequest.getSource().getCommit().getHash(); + String sourceCommit = pullRequest.getSource().getCommit().getHash(); + BitbucketPullRequestResponseValueRepository destination = pullRequest.getDestination(); String owner = destination.getRepository().getOwnerName(); String repositoryName = destination.getRepository().getRepositoryName(); + String destinationCommit = destination.getCommit().getHash(); + String id = pullRequest.getId(); List<BitbucketPullRequestComment> comments = client.getPullRequestComments(owner, repositoryName, id); - String searchStartMarker = String.format(BUILD_START_MARKER, commit).toLowerCase(); - String searchFinishMarker = String.format(BUILD_FINISH_MARKER, commit).toLowerCase(); - + if (comments != null) { Collections.sort(comments); Collections.reverse(comments); - for(BitbucketPullRequestComment comment : comments) { + for (BitbucketPullRequestComment comment : comments) { String content = comment.getContent(); if (content == null || content.isEmpty()) { continue; } - content = content.toLowerCase(); - if (content.contains(searchStartMarker) || - content.contains(searchFinishMarker)) { - shouldBuild = false; - break; + + //These will match any start or finish message -- need to check commits + Matcher startMatcher = Pattern.compile(BUILD_START_REGEX, Pattern.CASE_INSENSITIVE).matcher(content); + Matcher finishMatcher = Pattern.compile(BUILD_FINISH_REGEX, Pattern.CASE_INSENSITIVE).matcher(content); + + if (startMatcher.find() || + finishMatcher.find()) { + + String sourceCommitMatch; + String destinationCommitMatch; + + if (startMatcher.find(0)) { + sourceCommitMatch = startMatcher.group(1); + destinationCommitMatch = startMatcher.group(2); + } else { + sourceCommitMatch = finishMatcher.group(1); + destinationCommitMatch = finishMatcher.group(2); + } + + //first check source commit -- if it doesn't match, just move on. If it does, investigate further. + if (sourceCommitMatch.equalsIgnoreCase(sourceCommit)) { + // if we're checking destination commits, and if this doesn't match, then move on. + if (this.trigger.getCheckDestinationCommit() + && (!destinationCommitMatch.equalsIgnoreCase(destinationCommit))) { + continue; + } + + shouldBuild = false; + break; + } } + if (content.contains(BUILD_REQUEST_MARKER.toLowerCase())) { shouldBuild = true; break; diff --git a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly index da12a64..ae93dcf 100644 --- a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly +++ b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly @@ -17,4 +17,7 @@ <f:entry title="CI Skip Phrases" field="ciSkipPhrases"> <f:textbox /> </f:entry> + <f:entry title="Rebuild if destination branch changes?" field="checkDestinationCommit"> + <f:checkbox /> + </f:entry> </j:jelly>
\ No newline at end of file diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly index 538998f..0404451 100644 --- a/src/main/resources/index.jelly +++ b/src/main/resources/index.jelly @@ -2,5 +2,5 @@ This view is used to render the installed plugins page. --> <div> - This plugin is a sample to explain how to write a Jenkins plugin. + This plugin polls BitBucket to determine whether there are Pull Requests that should be built. </div> |