From a6374a41b6ad80ca586a606823f6b22f5c5c4193 Mon Sep 17 00:00:00 2001 From: Olivier Bellemare Date: Thu, 27 Oct 2016 10:49:17 -0400 Subject: Add option to cancel outdated builds when a pull request is updated --- .../BitbucketBuildTrigger.java | 64 +++++++++++++++++++++- .../BitbucketBuildTrigger/config.jelly | 3 + src/test/java/BitbucketBuildRepositoryTest.java | 12 ++-- 3 files changed, 72 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java index aedfb91..90de6b5 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger.java @@ -7,20 +7,26 @@ import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredenti import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials; import hudson.Extension; import hudson.model.*; +import hudson.model.Queue; import hudson.model.queue.QueueTaskFuture; import hudson.plugins.git.RevisionParameterAction; import hudson.triggers.Trigger; import hudson.triggers.TriggerDescriptor; import hudson.util.ListBoxModel; +import jenkins.model.Jenkins; import net.sf.json.JSONObject; +import org.apache.commons.lang.StringUtils; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import static com.cloudbees.plugins.credentials.CredentialsMatchers.instanceOf; @@ -43,11 +49,12 @@ public class BitbucketBuildTrigger extends Trigger> { private final String ciSkipPhrases; private final boolean checkDestinationCommit; private final boolean approveIfSuccess; + private final boolean cancelOutdatedJobs; transient private BitbucketPullRequestsBuilder bitbucketPullRequestsBuilder; @Extension - public static final BitbucketBuildTriggerDescriptor descriptor = new BitbucketBuildTriggerDescriptor(); + public static final BitbucketBuildTriggerDescriptor descriptor = new BitbucketBuildTriggerDescriptor(); @DataBoundConstructor public BitbucketBuildTrigger( @@ -64,7 +71,8 @@ public class BitbucketBuildTrigger extends Trigger> { String ciName, String ciSkipPhrases, boolean checkDestinationCommit, - boolean approveIfSuccess + boolean approveIfSuccess, + boolean cancelOutdatedJobs ) throws ANTLRException { super(cron); this.projectPath = projectPath; @@ -81,6 +89,7 @@ public class BitbucketBuildTrigger extends Trigger> { this.ciSkipPhrases = ciSkipPhrases; this.checkDestinationCommit = checkDestinationCommit; this.approveIfSuccess = approveIfSuccess; + this.cancelOutdatedJobs = cancelOutdatedJobs; } public String getProjectPath() { @@ -114,7 +123,7 @@ public class BitbucketBuildTrigger extends Trigger> { public String getBranchesFilter() { return branchesFilter; } - + public boolean getBranchesFilterBySCMIncludes() { return branchesFilterBySCMIncludes; } @@ -139,6 +148,10 @@ public class BitbucketBuildTrigger extends Trigger> { return approveIfSuccess; } + public boolean getCancelOutdatedJobs() { + return cancelOutdatedJobs; + } + @Override public void start(AbstractProject project, boolean newInstance) { try { @@ -164,9 +177,54 @@ public class BitbucketBuildTrigger extends Trigger> { public QueueTaskFuture startJob(BitbucketCause cause) { Map values = this.getDefaultParameters(); + + if (getCancelOutdatedJobs()) { + cancelPreviousJobsInQueueThatMatch(cause); + abortRunningJobsThatMatch(cause); + } + return this.job.scheduleBuild2(0, cause, new ParametersAction(new ArrayList(values.values())), new RevisionParameterAction(cause.getSourceCommitHash())); } + private void cancelPreviousJobsInQueueThatMatch(@Nonnull BitbucketCause bitbucketCause) { + logger.fine("Looking for queued jobs that match PR ID: " + bitbucketCause.getPullRequestId()); + Queue queue = Jenkins.getInstance().getQueue(); + for (Queue.Item item : queue.getItems()) { + if (hasCauseFromTheSamePullRequest(item.getCauses(), bitbucketCause)) { + logger.info("Canceling item in queue: " + item); + queue.cancel(item); + } + } + } + + private void abortRunningJobsThatMatch(@Nonnull BitbucketCause bitbucketCause) { + logger.fine("Looking for running jobs that match PR ID: " + bitbucketCause.getPullRequestId()); + for (Object o : job.getBuilds()) { + if (o instanceof Build) { + Build build = (Build) o; + if (build.isBuilding() && hasCauseFromTheSamePullRequest(build.getCauses(), bitbucketCause)) { + logger.info("Aborting build: " + build + " since PR is outdated"); + build.getExecutor().interrupt(Result.ABORTED); + } + } + } + } + + private boolean hasCauseFromTheSamePullRequest(@Nullable List causes, @Nullable BitbucketCause pullRequestCause) { + if (causes != null && pullRequestCause != null) { + for (Cause cause : causes) { + if (cause instanceof BitbucketCause) { + BitbucketCause sc = (BitbucketCause) cause; + if (StringUtils.equals(sc.getPullRequestId(), pullRequestCause.getPullRequestId()) && + StringUtils.equals(sc.getRepositoryName(), pullRequestCause.getRepositoryName())) { + return true; + } + } + } + } + return false; + } + private Map getDefaultParameters() { Map values = new HashMap(); ParametersDefinitionProperty definitionProperty = this.job.getProperty(ParametersDefinitionProperty.class); diff --git a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly index d4b23da..971954f 100644 --- a/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly +++ b/src/main/resources/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketBuildTrigger/config.jelly @@ -38,4 +38,7 @@ + + + diff --git a/src/test/java/BitbucketBuildRepositoryTest.java b/src/test/java/BitbucketBuildRepositoryTest.java index 953bd81..148e504 100644 --- a/src/test/java/BitbucketBuildRepositoryTest.java +++ b/src/test/java/BitbucketBuildRepositoryTest.java @@ -118,7 +118,8 @@ public class BitbucketBuildRepositoryTest { "", true, "", "", "", true, - true + true, + false ); BitbucketPullRequestsBuilder builder = EasyMock.createMock(BitbucketPullRequestsBuilder.class); @@ -148,7 +149,8 @@ public class BitbucketBuildRepositoryTest { "", true, "", "", "", true, - true + true, + false ); BitbucketPullRequestsBuilder builder = EasyMock.createMock(BitbucketPullRequestsBuilder.class); @@ -202,7 +204,8 @@ public class BitbucketBuildRepositoryTest { "", true, "jenkins", "Jenkins", "", true, - true + true, + false ); BitbucketPullRequestsBuilder builder = EasyMock.createMock(BitbucketPullRequestsBuilder.class); @@ -248,7 +251,8 @@ public class BitbucketBuildRepositoryTest { "", true, "jenkins-too-long-ci-key", "Jenkins", "", true, - true + true, + false ); final MessageDigest MD5 = MessageDigest.getInstance("MD5"); -- cgit v1.2.3 From 703361bb82c9ea6e52525cfa0abb5b636eb55186 Mon Sep 17 00:00:00 2001 From: elifarley Date: Wed, 8 Feb 2017 16:57:53 -0200 Subject: Remove all "e.printStackTrace()" calls --- .../bitbucketpullrequestbuilder/bitbucket/ApiClient.java | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/ApiClient.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/ApiClient.java index 759c696..0c87478 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/ApiClient.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/bitbucket/ApiClient.java @@ -119,10 +119,8 @@ public class ApiClient { return new String(Hex.encodeHex(SHA1.digest(computedKey.getBytes("UTF-8")))); } catch(NoSuchAlgorithmException e) { logger.log(Level.WARNING, "Failed to create hash provider", e); - e.printStackTrace(); } catch (UnsupportedEncodingException e) { logger.log(Level.WARNING, "Failed to create hash provider", e); - e.printStackTrace(); } } return (computedKey.length() <= MAX_KEY_SIZE_BB_API) ? computedKey : computedKey.substring(0, MAX_KEY_SIZE_BB_API); @@ -173,7 +171,6 @@ public class ApiClient { new NameValuePair[]{}), Pullrequest.Participant.class); } catch (IOException e) { logger.log(Level.WARNING, "Invalid pull request approval response.", e); - e.printStackTrace(); } return null; } @@ -186,7 +183,6 @@ public class ApiClient { return parse(post(v1("/pullrequests/" + pullRequestId + "/comments"), data), new TypeReference() {}); } catch(Exception e) { logger.log(Level.WARNING, "Invalid pull request comment response.", e); - e.printStackTrace(); } return null; } @@ -203,7 +199,6 @@ public class ApiClient { } while (url != null); } catch (Exception e) { logger.log(Level.WARNING, "invalid response.", e); - e.printStackTrace(); } return values; } @@ -255,10 +250,8 @@ public class ApiClient { return req.getResponseBodyAsString(); } catch (HttpException e) { logger.log(Level.WARNING, "Failed to send request.", e); - e.printStackTrace(); } catch (IOException e) { logger.log(Level.WARNING, "Failed to send request.", e); - e.printStackTrace(); } finally { req.releaseConnection(); } -- cgit v1.2.3 From d79f5c0fdaf9a40970c83fb33916a17a060b198f Mon Sep 17 00:00:00 2001 From: elifarley Date: Wed, 8 Feb 2017 16:59:36 -0200 Subject: Remove all "e.printStackTrace()" calls --- .../bitbucketpullrequestbuilder/BitbucketPullRequestsBuilder.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketPullRequestsBuilder.java b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketPullRequestsBuilder.java index d337796..899edba 100644 --- a/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketPullRequestsBuilder.java +++ b/src/main/java/bitbucketpullrequestbuilder/bitbucketpullrequestbuilder/BitbucketPullRequestsBuilder.java @@ -69,10 +69,8 @@ public class BitbucketPullRequestsBuilder { return new String(Hex.encodeHex(MD5.digest(this.project.getFullName().getBytes("UTF-8")))); } catch (NoSuchAlgorithmException exc) { logger.log(Level.WARNING, "Failed to produce hash", exc); - exc.printStackTrace(); } catch (UnsupportedEncodingException exc) { logger.log(Level.WARNING, "Failed to produce hash", exc); - exc.printStackTrace(); } return this.project.getFullName(); } -- cgit v1.2.3