Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-26323] Fix "Build Current Patches Only" by scanning for event #195

Merged
merged 2 commits into from Jan 9, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -63,6 +63,7 @@
import com.sonymobile.tools.gerrit.gerritevents.dto.events.GerritTriggeredEvent;
import com.sonymobile.tools.gerrit.gerritevents.dto.events.RefUpdated;
import com.sonymobile.tools.gerrit.gerritevents.dto.rest.Notify;

import hudson.Extension;
import hudson.ExtensionList;
import hudson.Util;
Expand All @@ -71,6 +72,7 @@
import hudson.model.Action;
import hudson.model.Actionable;
import hudson.model.AutoCompletionCandidates;
import hudson.model.Cause;
import hudson.model.Computer;
import hudson.model.Executor;
import hudson.model.Hudson;
Expand All @@ -79,6 +81,7 @@
import hudson.model.Job;
import hudson.model.ParametersAction;
import hudson.model.Queue;
import hudson.model.Run;
import hudson.model.Result;
import hudson.triggers.Trigger;
import hudson.triggers.TriggerDescriptor;
Expand All @@ -94,6 +97,7 @@
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
Expand All @@ -105,6 +109,8 @@
import java.util.StringTokenizer;
import java.util.regex.PatternSyntaxException;

import jenkins.model.Jenkins;

import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
Expand Down Expand Up @@ -1835,7 +1841,7 @@ public synchronized void scheduled(ChangeBasedEvent event, ParametersAction para
if (((ChangeBasedEvent)pairs.getKey()).getChange().equals(event.getChange())) {
logger.debug("Cancelling build for " + pairs.getKey());
try {
cancelJob(pairs.getValue());
cancelJob(pairs.getKey());
} catch (Exception e) {
// Ignore any problems with canceling the job.
logger.error("Error canceling job", e);
Expand All @@ -1849,43 +1855,69 @@ public synchronized void scheduled(ChangeBasedEvent event, ParametersAction para
}

/**
* Tries to cancel any jobs with the specified parameters. We look in
* both the build queue and currently executing jobs. This extra work is
* required due to race conditions when calling Future.cancel() - see
* Tries to cancel any job, which was triggered by the given change event.
* <p>
* Since the event is always noted in the build cause, it is easy to
* identify which specific builds shall be cancelled, without having
* to dig down into the parameters, which might've been mutated by the
* build while it was running. (This was the previous implementation)
* <p>
* We look in both the build queue and currently executing jobs.
* This extra work is required due to race conditions when calling
* Future.cancel() - see
* https://issues.jenkins-ci.org/browse/JENKINS-13829
*
* @param parameters
* The parameters to match against.
* @param event
* The event that originally triggered the build.
*/
private void cancelJob(ParametersAction parameters) {
private void cancelJob(GerritTriggeredEvent event) {
// Remove any jobs in the build queue.
List<hudson.model.Queue.Item> itemsInQueue = Queue.getInstance().getItems(job);
for (hudson.model.Queue.Item item : itemsInQueue) {
List<ParametersAction> params = item.getActions(ParametersAction.class);
for (ParametersAction param : params) {
if (param.equals(parameters)) {
Queue.getInstance().cancel(item);
}
List<hudson.model.Queue.Item> itemsInQueue = Queue.getInstance().getItems(getJob());
for (hudson.model.Queue.Item item : itemsInQueue) {
if (checkCausedByGerrit(event, item.getCauses())) {
Queue.getInstance().cancel(item);
}
}
// Interrupt any currently running jobs.
for (Computer c : Hudson.getInstance().getComputers()) {
for (Computer c : Jenkins.getInstance().getComputers()) {
List<Executor> executors = new ArrayList<Executor>();
executors.addAll(c.getOneOffExecutors());
executors.addAll(c.getExecutors());
for (Executor e : executors) {
if (e.getCurrentExecutable() instanceof Actionable) {
Actionable a = (Actionable)e.getCurrentExecutable();
List<ParametersAction> params = a.getActions(ParametersAction.class);
for (ParametersAction param : params) {
if (param.equals(parameters)) {
e.interrupt(Result.ABORTED, new NewPatchSetInterruption());
}
if (e.getCurrentExecutable() instanceof Run<?,?>) {
Run<?,?> run = (Run<?,?>) e.getCurrentExecutable();
if (checkCausedByGerrit(event, run.getCauses())) {
e.interrupt(
Result.ABORTED,
new NewPatchSetInterruption()
);
}
}
}
}
}

/**
* Checks if any of the given causes references the given event.
*
* @param event The event to check for. Checks for <i>identity</i>, not
* <i>equality</i>!
* @param causes the list of causes. Only {@link GerritCause}s are considered.
* @return
*/
private boolean checkCausedByGerrit(GerritTriggeredEvent event, Collection<Cause> causes) {
for (Cause c : causes) {
if (!(c instanceof GerritCause)) {
continue;
}
GerritCause gc = (GerritCause) c;
if (gc.getEvent() == event) {
return true;
}
}
return false;
}


/**
* Removes any reference to the current build for this change.
Expand Down