Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-32823] Added "When no combinations to rerun"
  • Loading branch information
ikedam committed Feb 20, 2016
1 parent 0f1e8f2 commit 9ce342c
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 8 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
Expand Up @@ -15,13 +15,16 @@
import hudson.tasks.Publisher;
import net.sf.json.JSONObject;

import org.kohsuke.stapler.DataBoundSetter;
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 @@ -35,6 +38,7 @@ public class NaginatorPublisher extends Notifier {
private final boolean rerunMatrixPart;
private final boolean checkRegexp;
private final Boolean regexpForMatrixParent;
private NoChildStrategy noChildStrategy; /* almost final */

private ScheduleDelay delay;

Expand Down Expand Up @@ -109,6 +113,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 Down
Expand Up @@ -37,13 +37,15 @@ public class NaginatorPublisherScheduleAction extends NaginatorScheduleAction {
private final boolean rerunIfUnstable;
private final boolean checkRegexp;
private final boolean regexpForMatrixParent;
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.noChildStrategy = publisher.getNoChildStrategy();
}

@CheckForNull
Expand Down Expand Up @@ -230,4 +232,12 @@ private boolean parseLogImpl(final File logFile, @Nonnull final String regexp) t
}
}
}

@Override
@Nonnull
public NoChildStrategy getNoChildStrategy() {
return (noChildStrategy != null)
? noChildStrategy
: NoChildStrategy.getDefault();
}
}
Expand Up @@ -122,4 +122,14 @@ public boolean shouldSchedule(@Nonnull Run<?, ?> run, @Nonnull TaskListener list
public boolean shouldScheduleForMatrixRun(@Nonnull MatrixRun run, @Nonnull TaskListener listener) {
return true;
}

/**
* @return how to do when no children to rerun for a matrix project.
*
* @since 1.17
*/
@Nonnull
public NoChildStrategy getNoChildStrategy() {
return NoChildStrategy.getDefault();
}
}
@@ -0,0 +1,55 @@
/*
* The MIT License
*
* Copyright (c) 2016 IKEDA Yasuyuki
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.chikli.hudson.plugin.naginator;

import javax.annotation.Nonnull;

import org.jvnet.localizer.Localizable;

/**
* The strategy for no children to rerun.
*
* @since 1.17
*/
public enum NoChildStrategy {
RerunWhole(Messages._NoChildStrategy_RerunWhole_DisplayName()),
RerunEmpty(Messages._NoChildStrategy_RerunEmpty_DisplayName()),
DontRun(Messages._NoChildStrategy_DontRerun_DisplayName()),
;
private final Localizable displayName;

private NoChildStrategy(Localizable displayName) {
this.displayName = displayName;
}

public String getDisplayName() {
return displayName.toString();
}

@Nonnull
public static NoChildStrategy getDefault() {
return RerunWhole;
}
}
@@ -1,2 +1,4 @@
NaginatorCause.Description=Started by Naginator after build {0} failure

NoChildStrategy.RerunWhole.DisplayName=Rerun the matrix with all combinations
NoChildStrategy.RerunEmpty.DisplayName=Rerun the matrix with no combinations
NoChildStrategy.DontRerun.DisplayName=Don''t rerun
Expand Up @@ -3,9 +3,11 @@
<f:checkbox />
</f:entry>

<f:entry title="Rerun build only for failed parts on the matrix" field="rerunMatrixPart">
<f:checkbox />
</f:entry>
<j:if test="${descriptor.isMatrixProject(it)}">
<f:entry title="Rerun build only for failed parts on the matrix" field="rerunMatrixPart">
<f:checkbox />
</f:entry>
</j:if>

<f:entry title="${%Delay before retrying build}">
<j:invokeStatic var="delays" className="com.chikli.hudson.plugin.naginator.ScheduleDelay" method="all"/>
Expand All @@ -17,6 +19,11 @@
</f:entry>

<f:advanced>
<j:if test="${descriptor.isMatrixProject(it)}">
<f:entry title="${%When no combinations to rerun}" field="noChildStrategy">
<f:enum>${it.displayName}</f:enum>
</f:entry>
</j:if>
<f:optionalBlock field="checkRegexp" inline="true"
title="${%Only rerun build if regular expression is found in output}">
<f:entry title="${%Regular expression to search for}" field="regexpForRerun">
Expand Down
@@ -0,0 +1,12 @@
<div>
How to rerun the build if no combinations to rerun.
This configuration takes effect only when you check "Rerun build only for failed parts on the matrix".
<dl>
<dt>Rerun the matrix with all combinations</dt>
<dd>Reruns whole the matrix. This is useful if you want always rerun something.</dd>
<dt>Rerun the matrix with no combinations</dt>
<dd>Reruns the matrix with no children. This is useful if you want rerun only aggregation processes. Some processes may fail if no children.</dd>
<dt>Don't rerun</dt>
<dd>Doesn't rerun the matrix. This is useful especially when used with the regular expressions.</dd>
</dl>
</div>
@@ -0,0 +1,5 @@
<div>
Applicable only to multi-configuration projects.
Reruns only failed axes combinations.
If not checked, always reruns all the combinations.
</div>
Expand Up @@ -284,12 +284,18 @@ public void testConfigurationForRegexpOnMatrixProject() throws Exception {
1, // maxSchedule
new FixedDelay(0)
);
naginator.setNoChildStrategy(NoChildStrategy.RerunEmpty);

p.getPublishersList().add(naginator);

j.configRoundtrip(p);

j.assertEqualDataBoundBeans(naginator, p.getPublishersList().get(NaginatorPublisher.class));
// assertEqualDataBoundBeans doesn't work for DataBoundSetter fields.
assertEquals(
naginator.getNoChildStrategy(),
p.getPublishersList().get(NaginatorPublisher.class).getNoChildStrategy()
);
}


Expand All @@ -311,22 +317,29 @@ public void testConfigurationForRegexpOnFreeStyleProject() throws Exception {
1, // maxSchedule
new FixedDelay(0)
);
naginator.setNoChildStrategy(NoChildStrategy.RerunEmpty);
NaginatorPublisher expected = new NaginatorPublisher(
naginator.getRegexpForRerun(),
naginator.isRerunIfUnstable(),
naginator.isRerunMatrixPart(),
false, // retunMatrixPart (not preserved)
naginator.isCheckRegexp(),
false, // regexpForMatrixParent (not preserved)
naginator.getMaxSchedule(),
naginator.getDelay()
);
naginator.setNoChildStrategy(NoChildStrategy.getDefault()); // not preserved

p.getPublishersList().add(naginator);

j.configRoundtrip(p);

assertFalse(p.getPublishersList().get(NaginatorPublisher.class).isRegexpForMatrixParent());
j.assertEqualDataBoundBeans(expected, p.getPublishersList().get(NaginatorPublisher.class));
// assertEqualDataBoundBeans doesn't work for DataBoundSetter fields.
assertEquals(
expected.getNoChildStrategy(),
p.getPublishersList().get(NaginatorPublisher.class).getNoChildStrategy()
);
}

@Test
Expand Down
Expand Up @@ -93,10 +93,16 @@ public boolean shouldSchedule(Run<?, ?> run, TaskListener listener, int retryCou

private static class MatrixConfigurationScheduleAction extends NaginatorScheduleAction {
private final String combinationFilter;
private final NoChildStrategy noChildStrategy;

public MatrixConfigurationScheduleAction(String combinationFilter, int maxSchedule, ScheduleDelay delay, boolean rerunMatrixPart) {
public MatrixConfigurationScheduleAction(String combinationFilter, int maxSchedule, ScheduleDelay delay, boolean rerunMatrixPart, NoChildStrategy noChildStrategy) {
super(maxSchedule, delay, rerunMatrixPart);
this.combinationFilter = combinationFilter;
this.noChildStrategy = noChildStrategy;
}

public MatrixConfigurationScheduleAction(String combinationFilter, int maxSchedule, ScheduleDelay delay, boolean rerunMatrixPart) {
this(combinationFilter, maxSchedule, delay, rerunMatrixPart, NoChildStrategy.getDefault());
}

@Override
Expand All @@ -106,6 +112,11 @@ public boolean shouldScheduleForMatrixRun(MatrixRun run, TaskListener listener)
combinationFilter
);
}

@Override
public NoChildStrategy getNoChildStrategy() {
return noChildStrategy;
}
}

/**
Expand Down Expand Up @@ -353,9 +364,10 @@ public void testMatrixWithNoChildren() throws Exception {
p.getBuildersList().add(new ScheduleActionBuilder(
new MatrixConfigurationScheduleAction(
"false",
1,
maxSchedule,
new FixedDelay(0),
true
true,
NoChildStrategy.RerunWhole
)
));
p.scheduleBuild2(0);
Expand All @@ -371,6 +383,77 @@ public void testMatrixWithNoChildren() throws Exception {
assertNull(b.getExactRun(new Combination(axes, "2", "2")));
}

/**
* Filtering out all children with DontRerun strategy
* cause trigger nothing.
*
* @throws Exception
*/
@Test
public void testMatrixWithNoChildrenNoRerun() throws Exception {
final int maxSchedule = 1;

MatrixProject p = j.createMatrixProject();
AxisList axes = new AxisList(
new Axis("axis1", "1", "2"),
new Axis("axis2", "1", "2")
);
p.setAxes(axes);
p.setCombinationFilter("!(axis1=='2' && axis2=='2')");
p.getBuildersList().add(new ScheduleActionBuilder(
new MatrixConfigurationScheduleAction(
"false",
maxSchedule,
new FixedDelay(0),
true,
NoChildStrategy.DontRun
)
));
p.scheduleBuild2(0);
j.waitUntilNoActivity();

assertEquals(1, p.getLastBuild().number);
}

/**
* Filtering out all children cause trigger the matrix,
* but no children.
*
* @throws Exception
*/
@Test
public void testMatrixWithNoChildrenEmpty() throws Exception {
final int maxSchedule = 1;

MatrixProject p = j.createMatrixProject();
AxisList axes = new AxisList(
new Axis("axis1", "1", "2"),
new Axis("axis2", "1", "2")
);
p.setAxes(axes);
p.setCombinationFilter("!(axis1=='2' && axis2=='2')");
p.getBuildersList().add(new ScheduleActionBuilder(
new MatrixConfigurationScheduleAction(
"false",
maxSchedule,
new FixedDelay(0),
true,
NoChildStrategy.RerunEmpty
)
));
p.scheduleBuild2(0);
j.waitUntilNoActivity();

assertEquals(maxSchedule + 1, p.getLastBuild().number);

// No children are rescheduled
MatrixBuild b = p.getLastBuild();
assertNull(b.getExactRun(new Combination(axes, "1", "1")));
assertNull(b.getExactRun(new Combination(axes, "1", "2")));
assertNull(b.getExactRun(new Combination(axes, "2", "1")));
assertNull(b.getExactRun(new Combination(axes, "2", "2")));
}

/**
* Unsetting <code>rerunMatrixPart</code> triggers all children
* even if overriding {@link NaginatorScheduleAction#shouldScheduleForMatrixRun(MatrixRun, TaskListener)}
Expand Down

0 comments on commit 9ce342c

Please sign in to comment.