Skip to content

Commit

Permalink
Merge pull request #29 from ikedam/feature/JENKINS-32823_NoTriggerFor…
Browse files Browse the repository at this point in the history
…NoChild

[JENKINS-32823] [FIXED JENKINS-32821] Added "When no combinations to rerun" and "How to apply the regular expression to matrix"
  • Loading branch information
ikedam committed Mar 11, 2016
2 parents 0f1e8f2 + 7b9f2f2 commit 76c78c1
Show file tree
Hide file tree
Showing 13 changed files with 733 additions and 67 deletions.
Expand Up @@ -64,6 +64,19 @@ public void onCompleted(AbstractBuild<?, ?> build, @Nonnull TaskListener listene
if (!combsToRerun.isEmpty()) {
LOGGER.log(Level.FINE, "schedule matrix rebuild");
scheduleMatrixBuild(build, combsToRerun, n, retryCount + 1, action.getMaxSchedule());
} else if (build instanceof MatrixBuild && action.isRerunMatrixPart()) {
// No children to rerun
switch (action.getNoChildStrategy()) {
case RerunWhole:
scheduleBuild(build, n, retryCount + 1, action.getMaxSchedule());
break;
case RerunEmpty:
LOGGER.log(Level.FINE, "schedule matrix rebuild");
scheduleMatrixBuild(build, combsToRerun, n, retryCount + 1, action.getMaxSchedule());
break;
case DontRun:
continue; // confusing, but back to the look for NaginatorScheduleAction
}
} else {
scheduleBuild(build, n, retryCount + 1, action.getMaxSchedule());
}
Expand Down
135 changes: 110 additions & 25 deletions src/main/java/com/chikli/hudson/plugin/naginator/NaginatorPublisher.java
Expand Up @@ -13,15 +13,21 @@
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;
import net.sf.json.JSONObject;

import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;

import java.io.IOException;
import java.util.logging.Logger;

import javax.annotation.Nonnull;

/**
* Reschedules a build if the current one fails.
*
Expand All @@ -34,7 +40,10 @@ public class NaginatorPublisher extends Notifier {
private final boolean rerunIfUnstable;
private final boolean rerunMatrixPart;
private final boolean checkRegexp;
private final Boolean regexpForMatrixParent;
@Deprecated
private transient Boolean regexpForMatrixParent;
private RegexpForMatrixStrategy regexpForMatrixStrategy; /* almost final */
private NoChildStrategy noChildStrategy; /* almost final */

private ScheduleDelay delay;

Expand All @@ -48,55 +57,54 @@ public NaginatorPublisher(String regexpForRerun,
}

/**
* backward compatible constructor.
*
* Watch that <code>regexpForMatrixParent</code> gets <code>true</code>
* for the backward compatibility.
* constructor.
*/
@DataBoundConstructor
public NaginatorPublisher(String regexpForRerun,
boolean rerunIfUnstable,
boolean rerunMatrixPart,
boolean checkRegexp,
int maxSchedule,
ScheduleDelay delay) {
this(regexpForRerun, rerunIfUnstable, rerunMatrixPart, checkRegexp, true, maxSchedule, delay);
this.regexpForRerun = regexpForRerun;
this.rerunIfUnstable = rerunIfUnstable;
this.rerunMatrixPart = rerunMatrixPart;
this.checkRegexp = checkRegexp;
this.maxSchedule = maxSchedule;
this.delay = delay;
setRegexpForMatrixStrategy(RegexpForMatrixStrategy.TestParent); // backward compatibility with < 1.16
}

/**
* @since 1.16
* @deprecated use {@link #NaginatorPublisher(String, boolean, boolean, boolean, int, ScheduleDelay)} and other setters
*/
@DataBoundConstructor
@Deprecated
public NaginatorPublisher(String regexpForRerun,
boolean rerunIfUnstable,
boolean rerunMatrixPart,
boolean checkRegexp,
boolean regexpForMatrixParent,
int maxSchedule,
ScheduleDelay delay) {
this.regexpForRerun = regexpForRerun;
this.rerunIfUnstable = rerunIfUnstable;
this.rerunMatrixPart = rerunMatrixPart;
this.checkRegexp = checkRegexp;
this.maxSchedule = maxSchedule;
this.regexpForMatrixParent = regexpForMatrixParent;
this.delay = delay;
this(regexpForRerun, rerunIfUnstable, rerunMatrixPart, checkRegexp, maxSchedule, delay);
setRegexpForMatrixParent(regexpForMatrixParent);
}

public Object readResolve() {
if (this.delay == null) {
// Backward compatibility : progressive 5 minutes up to 3 hours
delay = new ProgressiveDelay(5*60, 3*60*60);
}
if (regexpForMatrixParent == null) {
return new NaginatorPublisher(
regexpForRerun,
rerunIfUnstable,
rerunMatrixPart,
checkRegexp,
true, // true for backward compatibility.
maxSchedule,
delay
);
if (regexpForMatrixStrategy == null) {
if (regexpForMatrixParent != null) {
// >= 1.16
setRegexpForMatrixParent(regexpForMatrixParent.booleanValue());
regexpForMatrixParent = null;
} else {
// < 1.16
setRegexpForMatrixStrategy(RegexpForMatrixStrategy.TestParent);
}
}
return this;
}
Expand All @@ -109,6 +117,28 @@ public boolean isRerunMatrixPart() {
return rerunMatrixPart;
}

/**
* @param noChildStrategy
*
* @since 1.17
*/
@DataBoundSetter
public void setNoChildStrategy(@Nonnull NoChildStrategy noChildStrategy) {
this.noChildStrategy = noChildStrategy;
}

/**
* @return the strategy for no children to rerun for a matrix project.
*
* @since 1.17
*/
@Nonnull
public NoChildStrategy getNoChildStrategy() {
return (noChildStrategy != null)
? noChildStrategy
: NoChildStrategy.getDefault();
}

public boolean isCheckRegexp() {
return checkRegexp;
}
Expand All @@ -121,15 +151,43 @@ public boolean isCheckRegexp() {
*
* @return Returns whether apply the regexp to the matrix parent instead of matrix children
* @since 1.16
* @deprecated use {@link #getRegexpForMatrixStrategy()}
*/
@Deprecated
public boolean isRegexpForMatrixParent() {
return regexpForMatrixParent;
return (getRegexpForMatrixStrategy() == RegexpForMatrixStrategy.TestParent);
}

private void setRegexpForMatrixParent(boolean regexpForMatrixParent) {
setRegexpForMatrixStrategy(
regexpForMatrixParent
? RegexpForMatrixStrategy.TestParent
: RegexpForMatrixStrategy.TestChildrenRetriggerMatched // compatible with 1.16.
);
}

public String getRegexpForRerun() {
return regexpForRerun;
}

/**
* @param regexpForMatrixStrategy
* @since 1.17
*/
@DataBoundSetter
public void setRegexpForMatrixStrategy(@Nonnull RegexpForMatrixStrategy regexpForMatrixStrategy) {
this.regexpForMatrixStrategy = regexpForMatrixStrategy;
}

/**
* @return how to apply regexp for matrix builds.
* @since 1.17
*/
@Nonnull
public RegexpForMatrixStrategy getRegexpForMatrixStrategy() {
return regexpForMatrixStrategy;
}

public ScheduleDelay getDelay() {
return delay;
}
Expand All @@ -141,6 +199,13 @@ public int getMaxSchedule() {
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
if (build instanceof MatrixRun) {
if (
getRegexpForMatrixStrategy() == RegexpForMatrixStrategy.TestChildrenRetriggerMatched
&& !isRerunMatrixPart()
) {
listener.getLogger().println("[Naginator] Warning: TestChildrenRetriggerMatched doesn't work without rerunMatrixPart");
}

MatrixBuild parent = ((MatrixRun)build).getParentBuild();
if (parent.getAction(NaginatorPublisherScheduleAction.class) == null) {
// No strict exclusion is required
Expand Down Expand Up @@ -239,6 +304,26 @@ public Notifier newInstance(StaplerRequest req, JSONObject formData) throws Form
public boolean isMatrixProject(Object it) {
return (it instanceof MatrixProject);
}

public FormValidation doCheckRegexpForMatrixStrategy(
@QueryParameter RegexpForMatrixStrategy value,
@QueryParameter boolean rerunMatrixPart
) {
// called only when regexpForMatrixStrategy is displayed,
// and we can assume that this is a matrix project.
if (value == RegexpForMatrixStrategy.TestChildrenRetriggerMatched && !rerunMatrixPart) {
return FormValidation.warning(Messages.NaginatorPublisher_RegexpForMatrixStrategy_RerunMatrixPartShouldBeEnabled());
}
return FormValidation.ok();
}

public ListBoxModel doFillRegexpForMatrixStrategyItems() {
ListBoxModel ret = new ListBoxModel();
for (RegexpForMatrixStrategy strategy: RegexpForMatrixStrategy.values()) {
ret.add(strategy.getDisplayName(), strategy.name());
}
return ret;
}
}

private static final Logger LOGGER = Logger.getLogger(NaginatorPublisher.class.getName());
Expand Down
Expand Up @@ -36,14 +36,34 @@ public class NaginatorPublisherScheduleAction extends NaginatorScheduleAction {
private final String regexpForRerun;
private final boolean rerunIfUnstable;
private final boolean checkRegexp;
private final boolean regexpForMatrixParent;
private transient Boolean regexpForMatrixParent; // for backward compatibility
private /* almost final */ RegexpForMatrixStrategy regexpForMatrixStrategy;
private final NoChildStrategy noChildStrategy;

public NaginatorPublisherScheduleAction(NaginatorPublisher publisher) {
super(publisher.getMaxSchedule(), publisher.getDelay(), publisher.isRerunMatrixPart());
this.regexpForRerun = publisher.getRegexpForRerun();
this.rerunIfUnstable = publisher.isRerunIfUnstable();
this.regexpForMatrixParent = publisher.isRegexpForMatrixParent();
this.checkRegexp = publisher.isCheckRegexp();
this.regexpForMatrixStrategy = publisher.getRegexpForMatrixStrategy();
this.noChildStrategy = publisher.getNoChildStrategy();
}

public Object readResolve() {
if (regexpForMatrixStrategy == null) {
// < 1.17
if (regexpForMatrixParent != null) {
regexpForMatrixStrategy =
regexpForMatrixParent.booleanValue()
? RegexpForMatrixStrategy.TestParent
: RegexpForMatrixStrategy.TestChildrenRetriggerMatched;
regexpForMatrixParent = null;
} else {
// something strange.
regexpForMatrixStrategy = RegexpForMatrixStrategy.getDefault();
}
}
return this;
}

@CheckForNull
Expand All @@ -59,43 +79,69 @@ public boolean isCheckRegexp() {
return checkRegexp;
}

/**
* @deprecated use {@link #getRegexpForMatrixStrategy()}
*/
@Deprecated
public boolean isRegexpForMatrixParent() {
return regexpForMatrixParent;
return getRegexpForMatrixStrategy() == RegexpForMatrixStrategy.TestParent;
}

/**
* @since 1.17
*/
@Nonnull
public RegexpForMatrixStrategy getRegexpForMatrixStrategy() {
return regexpForMatrixStrategy;
}

@Override
public boolean shouldSchedule(@Nonnull Run<?, ?> run, @Nonnull TaskListener listener, int retryCount) {
if ((run.getResult() == Result.SUCCESS) || (run.getResult() == Result.ABORTED)) {
return false;
}

// If we're not set to rerun if unstable, and the build's unstable, return true.
if ((!isRerunIfUnstable()) && (run.getResult() == Result.UNSTABLE)) {
if (!checkCommonScheduleThreshold(run)) {
return false;
}

// If we're supposed to check for a regular expression in the build output before
// scheduling a new build, do so.
if (isCheckRegexp() && (!(run instanceof MatrixBuild) || isRegexpForMatrixParent())) {
if (isCheckRegexp() && (!(run instanceof MatrixBuild) || getRegexpForMatrixStrategy() == RegexpForMatrixStrategy.TestParent)) {
LOGGER.log(Level.FINEST, "Got checkRegexp == true");

if (!testRegexp(run, listener)) {
return false;
}
} else if (
isCheckRegexp()
&& (run instanceof MatrixBuild)
&& getRegexpForMatrixStrategy() == RegexpForMatrixStrategy.TestChildrenRetriggerAll
) {
// check should be performed for child builds here.
if (!testRegexpForFailedChildren((MatrixBuild)run, listener)) {
return false;
}
}

return super.shouldSchedule(run, listener, retryCount);
}

private boolean testRegexpForFailedChildren(@Nonnull MatrixBuild run, @Nonnull TaskListener listener) {
for (MatrixRun r : ((MatrixBuild)run).getExactRuns()) {
if (!checkCommonScheduleThreshold(r)) {
continue;
}
if (testRegexp(r, listener)) {
return true;
}
}
// no children matched.
return false;
}

@Override
public boolean shouldScheduleForMatrixRun(@Nonnull MatrixRun run, @Nonnull TaskListener listener) {
if ((run.getResult() == Result.SUCCESS) || (run.getResult() == Result.ABORTED)) {
return false;
}
if ((!isRerunIfUnstable()) && (run.getResult() == Result.UNSTABLE)) {
if (!checkCommonScheduleThreshold(run)) {
return false;
}
if (isCheckRegexp() && !isRegexpForMatrixParent()) {
if (isCheckRegexp() && getRegexpForMatrixStrategy() == RegexpForMatrixStrategy.TestChildrenRetriggerMatched) {
LOGGER.log(Level.FINEST, "Got isRerunMatrixPart == true");

if (!testRegexp(run, listener)) {
Expand All @@ -105,6 +151,18 @@ public boolean shouldScheduleForMatrixRun(@Nonnull MatrixRun run, @Nonnull TaskL
return true;
}

private boolean checkCommonScheduleThreshold(@Nonnull Run<?, ?> run) {
if ((run.getResult() == Result.SUCCESS) || (run.getResult() == Result.ABORTED)) {
return false;
}

// If we're not set to rerun if unstable, and the build's unstable, return true.
if ((!isRerunIfUnstable()) && (run.getResult() == Result.UNSTABLE)) {
return false;
}
return true;
}

private boolean testRegexp(@Nonnull Run<?, ?> run, TaskListener listener) {
String regexpForRerun = getRegexpForRerun();
if ((regexpForRerun != null) && (!regexpForRerun.equals(""))) {
Expand Down Expand Up @@ -230,4 +288,12 @@ private boolean parseLogImpl(final File logFile, @Nonnull final String regexp) t
}
}
}

@Override
@Nonnull
public NoChildStrategy getNoChildStrategy() {
return (noChildStrategy != null)
? noChildStrategy
: NoChildStrategy.getDefault();
}
}

0 comments on commit 76c78c1

Please sign in to comment.