Skip to content
Permalink
Browse files
[fixed JENKINS-14070] add limit to number of schedules
(also fix tests)
  • Loading branch information
ndeloof committed Jun 12, 2012
1 parent 1642c63 commit 6a7ba3cf00ec2697e26e8884d88326028504be4f
@@ -1,9 +1,6 @@
package com.chikli.hudson.plugin.naginator;

import hudson.model.AbstractBuild;
import hudson.model.ParametersAction;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.model.*;
import hudson.model.listeners.RunListener;

import java.io.BufferedReader;
@@ -15,6 +12,8 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static hudson.model.Result.SUCCESS;

/**
* @author <a href="mailto:nicolas.deloof@cloudbees.com">Nicolas De loof</a>
*/
@@ -23,7 +22,7 @@ public class NaginatorListener extends RunListener<AbstractBuild<?,?>> {

@Override
public void onCompleted(AbstractBuild<?, ?> build, TaskListener listener) {
if (build.getResult() == Result.SUCCESS) {
if (build.getResult() == SUCCESS) {
return;
}

@@ -62,12 +61,23 @@ public void onCompleted(AbstractBuild<?, ?> build, TaskListener listener) {
}
}

int n = naginator.getDelay().computeScheduleDelay(build);

LOGGER.log(Level.FINE, "about to try to schedule a build in " + n + " seconds");
scheduleBuild(build, n);
if (canSchedule(build, naginator)) {
int n = naginator.getDelay().computeScheduleDelay(build);
LOGGER.log(Level.FINE, "about to try to schedule a build in " + n + " seconds");
scheduleBuild(build, n);
} else {
LOGGER.log(Level.FINE, "max number of schedules for this build");
}
}

public boolean canSchedule(Run build, NaginatorPublisher naginator) {
Run r = build;
int max = naginator.getMaxSchedule();
if (max <=0) return true;
int n = 0;
for(; r!=null && r.getResult()!= SUCCESS && n++ <= max; r=r.getPreviousBuild()) {}
return n < max;
}

/**
* Wrapper method for mocking purposes.
@@ -28,13 +28,25 @@ public class NaginatorPublisher extends Notifier {

private ScheduleDelay delay;

private int maxSchedule;

// backward compatible constructor
public NaginatorPublisher(String regexpForRerun,
boolean rerunIfUnstable,
boolean checkRegexp) {
this(regexpForRerun, rerunIfUnstable, checkRegexp, 0, new ProgressiveDelay(5*60, 3*60*60));
}

@DataBoundConstructor
public NaginatorPublisher(String regexpForRerun,
boolean rerunIfUnstable,
boolean checkRegexp, ScheduleDelay delay) {
boolean checkRegexp,
int maxSchedule,
ScheduleDelay delay) {
this.regexpForRerun = regexpForRerun;
this.checkRegexp = checkRegexp;
this.rerunIfUnstable = rerunIfUnstable;
this.maxSchedule = maxSchedule;
this.delay = delay;
}

@@ -62,6 +74,10 @@ public ScheduleDelay getDelay() {
return delay;
}

public int getMaxSchedule() {
return maxSchedule;
}

@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
// Nothing to do during the build, see NaginatorListener
@@ -8,6 +8,10 @@
<f:hetero-radio descriptors="${delays}" field="delay"/>
</f:entry>

<f:entry title="Max number of successive failed build" field="maxSchedule">
<f:textbox/>
</f:entry>

<f:advanced>
<f:entry field="checkRegexp"
title="Only rerun build if regular expression is found in output">
@@ -0,0 +1,3 @@
<div>
Limits the number of successive job schedules after a build failure. Set to 0 for no limit.
</div>
@@ -0,0 +1,3 @@
<div>
This option allows to reschedule job upon failure.
</div>
@@ -0,0 +1,9 @@
<div xmlns="http://www.w3.org/1999/html">
if a build fails for a reason that cannot be immediately fixed,
immediate rescheduling may cause a very tight loop.
combined with publishers like e-mail, IM, this could flood the users.
<p>
So to avoid this problem, progressively introduce delay until the next build
delay = the number of consective build problems * <em>increment</em>
back off at most <em>max</em>
</div>
@@ -4,5 +4,5 @@
Since we don't really have anything dynamic here, let's just use static HTML.
-->
<div>
This plugin allows you to immediately reschedule upon failure.
This plugin allows you to reschedule job upon failure.
</div>
@@ -95,7 +95,7 @@ public void testWithBuildWrapper() throws Exception {

FreeStyleProject project = createFreeStyleProject();
project.getBuildersList().add(new MyBuilder("foo", Result.SUCCESS, 1000));
NaginatorPublisher nag = new NaginatorPublisher("foo", false, false, new FixedDelay(0));
NaginatorPublisher nag = new NaginatorPublisher("foo", false, false);
project.getPublishersList().add(nag);
BuildWrapper failTheBuild = new FailTheBuild();
project.getBuildWrappersList().add(failTheBuild);
@@ -108,7 +108,7 @@ private boolean isScheduledForRetry(String buildLog, Result result, String regex
boolean rerunIfUnstable, boolean checkRegexp) throws Exception {
FreeStyleProject project = createFreeStyleProject();
project.getBuildersList().add(new MyBuilder(buildLog, result));
NaginatorPublisher nag = new NaginatorPublisher(regexpForRerun, rerunIfUnstable, checkRegexp, new FixedDelay(0));
NaginatorPublisher nag = new NaginatorPublisher(regexpForRerun, rerunIfUnstable, checkRegexp);
project.getPublishersList().add(nag);

return isScheduledForRetry(project);

0 comments on commit 6a7ba3c

Please sign in to comment.