From 564b6681dffd561facc63be256e88514f52c9e1b Mon Sep 17 00:00:00 2001 From: Nicholas Blair Date: Fri, 29 May 2015 13:53:07 -0500 Subject: Parameterize comment phrase to trigger a build Defaults to prior "test this please", can be overridden in the job configuration. --- .../BitbucketBuildTrigger.java | 104 ++++++++++++++------- .../BitbucketRepository.java | 89 +++++++++--------- 2 files changed, 115 insertions(+), 78 deletions(-) diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java index aedfb91..10d6c98 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java @@ -28,6 +28,11 @@ import static com.cloudbees.plugins.credentials.CredentialsMatchers.instanceOf; * Created by nishio */ public class BitbucketBuildTrigger extends Trigger> { + /** + * Default value for {@link #getCommentTrigger()}. + */ + public static final String DEFAULT_COMMENT_TRIGGER = "test this please"; + private static final Logger logger = Logger.getLogger(BitbucketBuildTrigger.class.getName()); private final String projectPath; private final String cron; @@ -43,44 +48,71 @@ public class BitbucketBuildTrigger extends Trigger> { private final String ciSkipPhrases; private final boolean checkDestinationCommit; private final boolean approveIfSuccess; + private final String commentTrigger; transient private BitbucketPullRequestsBuilder bitbucketPullRequestsBuilder; @Extension - public static final BitbucketBuildTriggerDescriptor descriptor = new BitbucketBuildTriggerDescriptor(); + public static final BitbucketBuildTriggerDescriptor descriptor = new BitbucketBuildTriggerDescriptor(); + /** + * Sets {@link #getCommentTrigger()} to {@link #DEFAULT_COMMENT_TRIGGER}. + */ + @DataBoundConstructor + public BitbucketBuildTrigger( + String projectPath, + String cron, + String credentialsId, + String username, + String password, + String repositoryOwner, + String repositoryName, + String branchesFilter, + boolean branchesFilterBySCMIncludes, + String ciKey, + String ciName, + String ciSkipPhrases, + boolean checkDestinationCommit, + boolean approveIfSuccess + ) throws ANTLRException { + this(projectPath, cron, credentialsId, username, password, repositoryOwner, repositoryName, + branchesFilter, branchesFilterBySCMIncludes, ciKey, ciName, ciSkipPhrases, + checkDestinationCommit, approveIfSuccess, DEFAULT_COMMENT_TRIGGER); + } @DataBoundConstructor public BitbucketBuildTrigger( - String projectPath, - String cron, - String credentialsId, - String username, - String password, - String repositoryOwner, - String repositoryName, - String branchesFilter, - boolean branchesFilterBySCMIncludes, - String ciKey, - String ciName, - String ciSkipPhrases, - boolean checkDestinationCommit, - boolean approveIfSuccess - ) throws ANTLRException { - super(cron); - this.projectPath = projectPath; - this.cron = cron; - this.credentialsId = credentialsId; - this.username = username; - this.password = password; - this.repositoryOwner = repositoryOwner; - this.repositoryName = repositoryName; - this.branchesFilter = branchesFilter; - this.branchesFilterBySCMIncludes = branchesFilterBySCMIncludes; - this.ciKey = ciKey; - this.ciName = ciName; - this.ciSkipPhrases = ciSkipPhrases; - this.checkDestinationCommit = checkDestinationCommit; - this.approveIfSuccess = approveIfSuccess; + String projectPath, + String cron, + String credentialsId, + String username, + String password, + String repositoryOwner, + String repositoryName, + String branchesFilter, + boolean branchesFilterBySCMIncludes, + String ciKey, + String ciName, + String ciSkipPhrases, + boolean checkDestinationCommit, + boolean approveIfSuccess, + String commentTrigger + ) throws ANTLRException { + super(cron); + this.projectPath = projectPath; + this.cron = cron; + this.credentialsId = credentialsId; + this.username = username; + this.password = password; + this.repositoryOwner = repositoryOwner; + this.repositoryName = repositoryName; + this.branchesFilter = branchesFilter; + this.branchesFilterBySCMIncludes = branchesFilterBySCMIncludes; + this.ciKey = ciKey; + this.ciName = ciName; + this.ciSkipPhrases = ciSkipPhrases; + this.checkDestinationCommit = checkDestinationCommit; + this.approveIfSuccess = approveIfSuccess; + this.commentTrigger = commentTrigger; } public String getProjectPath() { @@ -114,7 +146,7 @@ public class BitbucketBuildTrigger extends Trigger> { public String getBranchesFilter() { return branchesFilter; } - + public boolean getBranchesFilterBySCMIncludes() { return branchesFilterBySCMIncludes; } @@ -136,7 +168,13 @@ public class BitbucketBuildTrigger extends Trigger> { } public boolean getApproveIfSuccess() { - return approveIfSuccess; + return approveIfSuccess; + } + /** + * @return a phrase that when entered in a comment will trigger a new build + */ + public String getCommentTrigger() { + return commentTrigger; } @Override diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java index 660ec21..ee11e75 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java @@ -35,7 +35,6 @@ import static com.cloudbees.plugins.credentials.CredentialsMatchers.instanceOf; public class BitbucketRepository { private static final Logger logger = Logger.getLogger(BitbucketRepository.class.getName()); private static final String BUILD_DESCRIPTION = "%s: %s into %s"; - private static final String BUILD_REQUEST_MARKER = "test this please"; private static final String BUILD_REQUEST_DONE_MARKER = "ttp build flag"; private static final String BUILD_REQUEST_MARKER_TAG_SINGLE_RX = "\\#[\\w\\-\\d]+"; private static final String BUILD_REQUEST_MARKER_TAGS_RX = "\\[bid\\:\\s?(.*)\\]"; @@ -44,7 +43,7 @@ public class BitbucketRepository { private BitbucketPullRequestsBuilder builder; private BitbucketBuildTrigger trigger; private ApiClient client; - + public BitbucketRepository(String projectPath, BitbucketPullRequestsBuilder builder) { this.projectPath = projectPath; this.builder = builder; @@ -53,26 +52,26 @@ public class BitbucketRepository { public void init() { this.init(null, null); } - + public void init(T httpFactory) { this.init(null, httpFactory); } - + public void init(ApiClient client) { this.init(client, null); } - + public void init(ApiClient client, T httpFactory) { this.trigger = this.builder.getTrigger(); - - if (client == null) { + + if (client == null) { String username = trigger.getUsername(); - String password = trigger.getPassword(); + String password = trigger.getPassword(); StandardUsernamePasswordCredentials credentials = getCredentials(trigger.getCredentialsId()); if (credentials != null) { username = credentials.getUsername(); password = credentials.getPassword().getPlainText(); - } + } this.client = new ApiClient( username, password, @@ -82,7 +81,7 @@ public class BitbucketRepository { trigger.getCiName(), httpFactory ); - + } else this.client = client; } @@ -97,7 +96,7 @@ public class BitbucketRepository { } return targetPullRequests; } - + public ApiClient getClient() { return this.client; } @@ -148,23 +147,23 @@ public class BitbucketRepository { public void postPullRequestApproval(String pullRequestId) { this.client.postPullRequestApproval(pullRequestId); } - + public String getMyBuildTag(String buildKey) { return "#" + this.client.buildStatusKey(buildKey); - } - + } + final static Pattern BUILD_TAGS_RX = Pattern.compile(BUILD_REQUEST_MARKER_TAGS_RX, Pattern.CASE_INSENSITIVE | Pattern.CANON_EQ); - final static Pattern SINGLE_BUILD_TAG_RX = Pattern.compile(BUILD_REQUEST_MARKER_TAG_SINGLE_RX, Pattern.CASE_INSENSITIVE | Pattern.CANON_EQ); - final static String CONTENT_PART_TEMPLATE = "```[bid: %s]```"; - + final static Pattern SINGLE_BUILD_TAG_RX = Pattern.compile(BUILD_REQUEST_MARKER_TAG_SINGLE_RX, Pattern.CASE_INSENSITIVE | Pattern.CANON_EQ); + final static String CONTENT_PART_TEMPLATE = "```[bid: %s]```"; + private List getAvailableBuildTagsFromTTPComment(String buildTags) { logger.log(Level.INFO, "Parse {0}", new Object[]{ buildTags }); - List availableBuildTags = new LinkedList(); + List availableBuildTags = new LinkedList(); Matcher subBuildTagMatcher = SINGLE_BUILD_TAG_RX.matcher(buildTags); while(subBuildTagMatcher.find()) availableBuildTags.add(subBuildTagMatcher.group(0).trim()); return availableBuildTags; } - + public boolean hasMyBuildTagInTTPComment(String content, String buildKey) { Matcher tagsMatcher = BUILD_TAGS_RX.matcher(content); if (tagsMatcher.find()) { @@ -172,40 +171,40 @@ public class BitbucketRepository { return this.getAvailableBuildTagsFromTTPComment(tagsMatcher.group(1).trim()).contains(this.getMyBuildTag(buildKey)); } else return false; - } - - private void postBuildTagInTTPComment(String pullRequestId, String content, String buildKey) { + } + + private void postBuildTagInTTPComment(String pullRequestId, String content, String buildKey) { logger.log(Level.INFO, "Update build tag for {0} build key", buildKey); List builds = this.getAvailableBuildTagsFromTTPComment(content); - builds.add(this.getMyBuildTag(buildKey)); + builds.add(this.getMyBuildTag(buildKey)); content += " " + String.format(CONTENT_PART_TEMPLATE, StringUtils.join(builds, " ")); logger.log(Level.INFO, "Post comment: {0} with original content {1}", new Object[]{ content, this.client.postPullRequestComment(pullRequestId, content).getId() }); } - + private boolean isTTPComment(String content) { - return content.toLowerCase().contains(BUILD_REQUEST_MARKER.toLowerCase()); + return content.toLowerCase().contains(trigger.getCommentTrigger().toLowerCase()); } - + private boolean isTTPCommentBuildTags(String content) { return content.toLowerCase().contains(BUILD_REQUEST_DONE_MARKER.toLowerCase()); } - + public List filterPullRequestComments(List comments) { logger.info("Filter PullRequest Comments."); Collections.sort(comments); - Collections.reverse(comments); - List filteredComments = new LinkedList(); + Collections.reverse(comments); + List filteredComments = new LinkedList(); for(Pullrequest.Comment comment : comments) { String content = comment.getContent(); - if (content == null || content.isEmpty()) continue; - boolean isTTP = this.isTTPComment(content); - boolean isTTPBuild = this.isTTPCommentBuildTags(content); + if (content == null || content.isEmpty()) continue; + boolean isTTP = this.isTTPComment(content); + boolean isTTPBuild = this.isTTPCommentBuildTags(content); if (isTTP || isTTPBuild) filteredComments.add(comment); if (isTTP) break; } return filteredComments; } - + private boolean isBuildTarget(Pullrequest pullRequest) { if (pullRequest.getState() != null && pullRequest.getState().equals("OPEN")) { if (isSkipBuild(pullRequest.getTitle()) || !isFilteredBuild(pullRequest)) { @@ -224,8 +223,8 @@ public class BitbucketRepository { final boolean commitAlreadyBeenProcessed = this.client.hasBuildStatus( sourceRepository.getOwnerName(), sourceRepository.getRepositoryName(), sourceCommit, buildKeyPart ); - if (commitAlreadyBeenProcessed) logger.log(Level.INFO, - "Commit {0}#{1} has already been processed", + if (commitAlreadyBeenProcessed) logger.log(Level.INFO, + "Commit {0}#{1} has already been processed", new Object[]{ sourceCommit, buildKeyPart } ); @@ -238,18 +237,18 @@ public class BitbucketRepository { boolean hasMyBuildTag = false; for (Pullrequest.Comment comment : filteredComments) { String content = comment.getContent(); - if (this.isTTPComment(content)) { + if (this.isTTPComment(content)) { rebuildCommentAvailable = true; - logger.log(Level.INFO, - "Rebuild comment available for commit {0} and comment #{1}", + logger.log(Level.INFO, + "Rebuild comment available for commit {0} and comment #{1}", new Object[]{ sourceCommit, comment.getId() } - ); + ); } if (isTTPCommentBuildTags(content)) hasMyBuildTag |= this.hasMyBuildTagInTTPComment(content, buildKeyPart); } rebuildCommentAvailable &= !hasMyBuildTag; - } + } if (rebuildCommentAvailable) this.postBuildTagInTTPComment(id, "TTP build flag", buildKeyPart); final boolean canBuildTarget = rebuildCommentAvailable || !commitAlreadyBeenProcessed; @@ -287,17 +286,17 @@ public class BitbucketRepository { pullRequest.getDestination().getCommit().getHash(), pullRequest.getAuthor().getCombinedUsername() ); - + //@FIXME: Way to iterate over all available SCMSources List sources = new LinkedList(); for(SCMSourceOwner owner : SCMSourceOwners.all()) for(SCMSource src : owner.getSCMSources()) - sources.add(src); - - BitbucketBuildFilter filter = !this.trigger.getBranchesFilterBySCMIncludes() ? + sources.add(src); + + BitbucketBuildFilter filter = !this.trigger.getBranchesFilterBySCMIncludes() ? BitbucketBuildFilter.InstanceByString(this.trigger.getBranchesFilter()) : BitbucketBuildFilter.InstanceBySCM(sources, this.trigger.getBranchesFilter()); - + return filter.approved(cause); } -- cgit v1.2.3 From 96e6cb666be9cce3f923e3eed39e5e08293c31c5 Mon Sep 17 00:00:00 2001 From: Nicholas Blair Date: Fri, 29 May 2015 14:26:01 -0500 Subject: Add config entry for commentTrigger field --- .../bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly index d4b23da..0992564 100644 --- a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly +++ b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly @@ -38,4 +38,7 @@ + + + -- cgit v1.2.3 From 83260d55784677708a6ab083b06c289ad528099f Mon Sep 17 00:00:00 2001 From: Nicholas Blair Date: Sat, 18 Feb 2017 16:13:33 -0600 Subject: fix: can't have 2 @DataBoundConstructors Refactor to move default value for commentTrigger to config.jelly. Handle special case in BitbucketBuildRepository where trigger field is null within unit tests (since BitbucketBuildTrigger can't be mocked or initialized in the test). --- .../BitbucketBuildTrigger.java | 29 ---------------------- .../BitbucketRepository.java | 11 +++++++- .../BitbucketBuildTrigger/config.jelly | 2 +- src/test/java/BitbucketBuildFilterTest.java | 6 +++-- src/test/java/BitbucketBuildRepositoryTest.java | 9 ++++--- 5 files changed, 20 insertions(+), 37 deletions(-) diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java index 10d6c98..81b5603 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java @@ -28,11 +28,6 @@ import static com.cloudbees.plugins.credentials.CredentialsMatchers.instanceOf; * Created by nishio */ public class BitbucketBuildTrigger extends Trigger> { - /** - * Default value for {@link #getCommentTrigger()}. - */ - public static final String DEFAULT_COMMENT_TRIGGER = "test this please"; - private static final Logger logger = Logger.getLogger(BitbucketBuildTrigger.class.getName()); private final String projectPath; private final String cron; @@ -55,30 +50,6 @@ public class BitbucketBuildTrigger extends Trigger> { @Extension public static final BitbucketBuildTriggerDescriptor descriptor = new BitbucketBuildTriggerDescriptor(); - /** - * Sets {@link #getCommentTrigger()} to {@link #DEFAULT_COMMENT_TRIGGER}. - */ - @DataBoundConstructor - public BitbucketBuildTrigger( - String projectPath, - String cron, - String credentialsId, - String username, - String password, - String repositoryOwner, - String repositoryName, - String branchesFilter, - boolean branchesFilterBySCMIncludes, - String ciKey, - String ciName, - String ciSkipPhrases, - boolean checkDestinationCommit, - boolean approveIfSuccess - ) throws ANTLRException { - this(projectPath, cron, credentialsId, username, password, repositoryOwner, repositoryName, - branchesFilter, branchesFilterBySCMIncludes, ciKey, ciName, ciSkipPhrases, - checkDestinationCommit, approveIfSuccess, DEFAULT_COMMENT_TRIGGER); - } @DataBoundConstructor public BitbucketBuildTrigger( String projectPath, diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java index ee11e75..01da88e 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketRepository.java @@ -38,6 +38,10 @@ public class BitbucketRepository { private static final String BUILD_REQUEST_DONE_MARKER = "ttp build flag"; private static final String BUILD_REQUEST_MARKER_TAG_SINGLE_RX = "\\#[\\w\\-\\d]+"; private static final String BUILD_REQUEST_MARKER_TAGS_RX = "\\[bid\\:\\s?(.*)\\]"; + /** + * Default value for comment trigger. + */ + public static final String DEFAULT_COMMENT_TRIGGER = "test this please"; private String projectPath; private BitbucketPullRequestsBuilder builder; @@ -182,7 +186,12 @@ public class BitbucketRepository { } private boolean isTTPComment(String content) { - return content.toLowerCase().contains(trigger.getCommentTrigger().toLowerCase()); + // special case: in unit tests, trigger is null and can't be mocked + String commentTrigger = DEFAULT_COMMENT_TRIGGER; + if(trigger != null && StringUtils.isNotBlank(trigger.getCommentTrigger())) { + commentTrigger = trigger.getCommentTrigger(); + } + return content.toLowerCase().contains(commentTrigger); } private boolean isTTPCommentBuildTags(String content) { diff --git a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly index 0992564..5f7c37c 100644 --- a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly +++ b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly @@ -39,6 +39,6 @@ - + diff --git a/src/test/java/BitbucketBuildFilterTest.java b/src/test/java/BitbucketBuildFilterTest.java index 3a94c82..2bc03fa 100644 --- a/src/test/java/BitbucketBuildFilterTest.java +++ b/src/test/java/BitbucketBuildFilterTest.java @@ -1,5 +1,7 @@ +import antlr.ANTLRException; import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.BitbucketBuildFilter; +import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.BitbucketBuildTrigger; import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.BitbucketCause; import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.BitbucketPullRequestsBuilder; import bitbucketpullrequestbuilder.bitbucketpullrequestbuilder.BitbucketRepository; @@ -194,8 +196,8 @@ public class BitbucketBuildFilterTest { @Test @WithoutJenkins - public void filterPRComments() { - BitbucketPullRequestsBuilder builder = EasyMock.createMock(BitbucketPullRequestsBuilder.class); + public void filterPRComments() throws ANTLRException { + BitbucketPullRequestsBuilder builder = EasyMock.createMock(BitbucketPullRequestsBuilder.class); EasyMock.expect(builder.getTrigger()).andReturn(null).anyTimes(); EasyMock.replay(builder); diff --git a/src/test/java/BitbucketBuildRepositoryTest.java b/src/test/java/BitbucketBuildRepositoryTest.java index 953bd81..7a338a7 100644 --- a/src/test/java/BitbucketBuildRepositoryTest.java +++ b/src/test/java/BitbucketBuildRepositoryTest.java @@ -118,7 +118,8 @@ public class BitbucketBuildRepositoryTest { "", true, "", "", "", true, - true + true, + BitbucketRepository.DEFAULT_COMMENT_TRIGGER ); BitbucketPullRequestsBuilder builder = EasyMock.createMock(BitbucketPullRequestsBuilder.class); @@ -148,7 +149,7 @@ public class BitbucketBuildRepositoryTest { "", true, "", "", "", true, - true + true, BitbucketRepository.DEFAULT_COMMENT_TRIGGER ); BitbucketPullRequestsBuilder builder = EasyMock.createMock(BitbucketPullRequestsBuilder.class); @@ -202,7 +203,7 @@ public class BitbucketBuildRepositoryTest { "", true, "jenkins", "Jenkins", "", true, - true + true, BitbucketRepository.DEFAULT_COMMENT_TRIGGER ); BitbucketPullRequestsBuilder builder = EasyMock.createMock(BitbucketPullRequestsBuilder.class); @@ -248,7 +249,7 @@ public class BitbucketBuildRepositoryTest { "", true, "jenkins-too-long-ci-key", "Jenkins", "", true, - true + true, BitbucketRepository.DEFAULT_COMMENT_TRIGGER ); final MessageDigest MD5 = MessageDigest.getInstance("MD5"); -- cgit v1.2.3