Skip to content
Permalink
Browse files

[FIXED JENKINS-32821] Introduced a new option "How to apply the regul…

…ar expression to matrix" which replaces "Test regular expression for the matrix parent"
  • Loading branch information...
ikedam committed Feb 27, 2016
1 parent 9ce342c commit 7b9f2f2a55f5f8b7ec286a73c55ec78d8270eb8f
@@ -13,9 +13,12 @@
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;
@@ -37,7 +40,9 @@
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;
@@ -52,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;
}
@@ -147,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;
}
@@ -167,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
@@ -265,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());
@@ -36,18 +36,36 @@
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
public String getRegexpForRerun() {
return regexpForRerun;
@@ -61,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)) {
if (!checkCommonScheduleThreshold(run)) {
return false;
}
if ((!isRerunIfUnstable()) && (run.getResult() == Result.UNSTABLE)) {
return false;
}
if (isCheckRegexp() && !isRegexpForMatrixParent()) {
if (isCheckRegexp() && getRegexpForMatrixStrategy() == RegexpForMatrixStrategy.TestChildrenRetriggerMatched) {
LOGGER.log(Level.FINEST, "Got isRerunMatrixPart == true");

if (!testRegexp(run, listener)) {
@@ -107,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(""))) {
@@ -0,0 +1,53 @@
/*
* 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;

/**
* How to apply regexp to matrix builds.
*/
public enum RegexpForMatrixStrategy {
TestChildrenRetriggerAll(Messages._RegexpForMatrixStrategy_TestChildrenRetriggerAll()),
TestChildrenRetriggerMatched(Messages._RegexpForMatrixStrategy_TestChildrenRetriggerMatched()),
TestParent(Messages._RegexpForMatrixStrategy_TestParent()),
;
private final Localizable displayName;

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

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

@Nonnull
public static RegexpForMatrixStrategy getDefault() {
return TestChildrenRetriggerAll;
}
}
@@ -1,4 +1,9 @@
NaginatorCause.Description=Started by Naginator after build {0} failure
RegexpForMatrixStrategy.TestChildrenRetriggerAll=Test failed matrix parts, and retrigger all
RegexpForMatrixStrategy.TestChildrenRetriggerMatched=Test failed matrix parts, and retrigger only matched parts
RegexpForMatrixStrategy.TestParent=Test the parent build
NoChildStrategy.RerunWhole.DisplayName=Rerun the matrix with all combinations
NoChildStrategy.RerunEmpty.DisplayName=Rerun the matrix with no combinations
NoChildStrategy.DontRerun.DisplayName=Don''t rerun
NaginatorPublisher.RegexpForMatrixStrategy.RerunMatrixPartShouldBeEnabled=You need to enable "Rerun build only for failed parts on the matrix" to use this strategy.

Oops, something went wrong.

0 comments on commit 7b9f2f2

Please sign in to comment.
You can’t perform that action at this time.