diff --git a/README.md b/README.md
index 05bbbb4..296a370 100644
--- a/README.md
+++ b/README.md
@@ -6,3 +6,8 @@ flakiness using the new "rerunFailingTestsCount" option. It also supports re-run
failed build at the exact failed Git revision.
Finally it aggregates statistics of tests (passes, fails and flakes) over Git revisions.
+
+The build parameter names can be changed via system properties:
+
+* jenkins.deflake.param.test (default to `test`)
+* jenkins.deflake.param.rerun_fail_test_count (default to `surefire.rerunFailingTestsCount`)
diff --git a/src/main/java/com/google/jenkins/flakyTestHandler/junit/FlakyTestResult.java b/src/main/java/com/google/jenkins/flakyTestHandler/junit/FlakyTestResult.java
index c64a60a..7ee2279 100644
--- a/src/main/java/com/google/jenkins/flakyTestHandler/junit/FlakyTestResult.java
+++ b/src/main/java/com/google/jenkins/flakyTestHandler/junit/FlakyTestResult.java
@@ -554,6 +554,9 @@ public void tally() {
*
* After the data is frozen, more files can be parsed
* and then freeze can be called again.
+ *
+ * @param parent parent action
+ * @param build current build
*/
public void freeze(AbstractTestResultAction parent, Run build) {
this.parentAction = parent;
diff --git a/src/main/java/com/google/jenkins/flakyTestHandler/plugin/FlakyTestResultAction.java b/src/main/java/com/google/jenkins/flakyTestHandler/plugin/FlakyTestResultAction.java
index b6ba8da..d40c84e 100644
--- a/src/main/java/com/google/jenkins/flakyTestHandler/plugin/FlakyTestResultAction.java
+++ b/src/main/java/com/google/jenkins/flakyTestHandler/plugin/FlakyTestResultAction.java
@@ -73,9 +73,12 @@ public class FlakyTestResultAction implements RunAction2 {
* Construct a FlakyTestResultAction object with Run and BuildListener
*
* @param build this build
+ * @param launcher launcher
* @param listener listener of this build
+ * @throws IOException when there's communication error
+ * @throws InterruptedException when not able to obtain channel
*/
- public FlakyTestResultAction(AbstractBuild build, Launcher launcher, TaskListener listener) throws IOException, InterruptedException {
+ public FlakyTestResultAction(AbstractBuild build, Launcher launcher, TaskListener listener) throws InterruptedException, IOException {
this.build = build;
// TODO consider the possibility that there is >1 such action
AbstractTestResultAction action = build.getAction(AbstractTestResultAction.class);
@@ -170,6 +173,9 @@ synchronized void setFlakyRunStats(FlakyRunStats stats) {
/**
* Overwrites the {@link FlakyRunStats} by a new data set.
+ *
+ * @param stats the flaky stats
+ * @param listener the listener
*/
public synchronized void setFlakyRunStats(FlakyRunStats stats, TaskListener listener) {
diff --git a/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeAction.java b/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeAction.java
index bd55a6d..26a7f3f 100644
--- a/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeAction.java
+++ b/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeAction.java
@@ -23,6 +23,7 @@
import hudson.model.Run;
import net.sf.json.JSONObject;
+import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
@@ -34,6 +35,7 @@
import java.util.Set;
import java.util.logging.Level;
+import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.servlet.ServletException;
@@ -60,7 +62,18 @@ public class DeflakeAction implements Action {
private static final String MAVEN_TEST_PARAM = "testParam";
- private static final String MAVEN_TEST = "test";
+ /**
+ * The name of the build parameter on the deflaked build which can be changed via system property
+ */
+ private static final String BUILD_PARAM_TEST =
+ System.getProperty("jenkins.deflake.param.test", "test");
+
+ /**
+ * The name of the build parameter on the deflaked build which can be changed via system property.
+ * This is useful when using failsafe plugin or for other scenarios.
+ */
+ private static final String BUILD_PARAM_RERUN_FAIL_TEST_COUNT =
+ System.getProperty("jenkins.deflake.param.rerun_fail_test_count", "surefire.rerunFailingTestsCount");
private static final String COMMA = ",";
@@ -79,9 +92,15 @@ public String apply(@Nonnull Entry> entry) {
};
private final Map> failingClassMethodMap;
+ private final Integer parentBuildNumber;
public DeflakeAction(Map> failingClassMethodMap) {
+ this(failingClassMethodMap, null);
+ }
+
+ public DeflakeAction(Map> failingClassMethodMap, Run, ?> parentBuild) {
this.failingClassMethodMap = failingClassMethodMap;
+ this.parentBuildNumber = (parentBuild != null) ? parentBuild.getNumber() : null;
}
@Override
@@ -110,10 +129,10 @@ public String getUrlName() {
*/
public void doIndex(StaplerRequest request, StaplerResponse response) throws
IOException, ServletException, InterruptedException {
- Run currentBuild = request.findAncestorObject(Run.class);
+ Run, ?> currentBuild = request.findAncestorObject(Run.class);
if (currentBuild != null) {
- Job job = currentBuild.getParent();
+ Job, ?> job = currentBuild.getParent();
job.checkPermission(AbstractProject.BUILD);
response.sendRedirect(DEFLAKE_CONFIG_URL);
}
@@ -121,26 +140,29 @@ public void doIndex(StaplerRequest request, StaplerResponse response) throws
/**
* Get parameters from submitted form and submit deflake request
+ *
+ * @param request request
+ * @param response response
+ * @throws ServletException when unable to parse input form
+ * @throws IOException when unable to redirect
*/
- public void doSubmitDeflakeRequest(StaplerRequest request, StaplerResponse response) throws
- IOException, ServletException, InterruptedException {
+ public void doSubmitDeflakeRequest(StaplerRequest request, StaplerResponse response) throws ServletException, IOException {
- Run run = request.findAncestorObject(Run.class);
+ Run,?> run = request.findAncestorObject(Run.class);
if (run != null) {
- Job job = run.getParent();
+ Job, ?> job = run.getParent();
job.checkPermission(AbstractProject.BUILD);
- List actions = constructDeflakeCause(run);
JSONObject formData = request.getSubmittedForm();
List parameterValues = new ArrayList();
- parameterValues.add(getStringParam(formData, RERUN_FAILING_TESTS_COUNT_PARAM));
+ String rerunFailTestCount = getStringParam(formData, RERUN_FAILING_TESTS_COUNT_PARAM, "0");
+ parameterValues.add(new StringParameterValue(BUILD_PARAM_RERUN_FAIL_TEST_COUNT, rerunFailTestCount));
- JSONObject paramObj = JSONObject.fromObject(formData.get(MAVEN_TEST_PARAM));
- boolean onlyRunFailingTests = paramObj.getBoolean("value");
+ boolean onlyRunFailingTests = getBooleanParam(formData, MAVEN_TEST_PARAM);
if (onlyRunFailingTests) {
String testParameter = generateMavenTestParams();
if (testParameter != null) {
- parameterValues.add(new StringParameterValue(MAVEN_TEST, testParameter));
+ parameterValues.add(new StringParameterValue(BUILD_PARAM_TEST, testParameter));
}
}
@@ -149,9 +171,10 @@ public void doSubmitDeflakeRequest(StaplerRequest request, StaplerResponse respo
originalParamAction = new ParametersAction();
}
+ List actions = constructDeflakeCause(run);
actions.add(originalParamAction.createUpdated(parameterValues));
- Jenkins.getInstance().getQueue().schedule((Queue.Task) run.getParent(), 0, actions);
+ Jenkins.get().getQueue().schedule2((Queue.Task) run.getParent(), 0, actions);
}
response.sendRedirect("../../");
@@ -181,19 +204,23 @@ private static List constructDeflakeCause(Run up) {
return actions;
}
- private static ParameterValue getBooleanParam(JSONObject formData, String paramName) {
+ private static boolean getBooleanParam(JSONObject formData, String paramName) {
JSONObject paramObj = JSONObject.fromObject(formData.get(paramName));
- String name = paramObj.getString("name");
- FlakyTestResultAction.logger.log(Level.FINE,
- "Param: " + name + " with value: " + paramObj.getBoolean("value"));
- return new BooleanParameterValue(name, paramObj.getBoolean("value"));
+ return paramObj.getBoolean("value");
}
- private static ParameterValue getStringParam(JSONObject formData, String paramName) {
+ private static String getStringParam(JSONObject formData, String paramName, String defaultValue) {
JSONObject paramObj = JSONObject.fromObject(formData.get(paramName));
- String name = paramObj.getString("name");
- FlakyTestResultAction.logger.log(Level.FINE,
- "Param: " + name + " with value: " + paramObj.getString("value"));
- return new StringParameterValue(name, paramObj.getString("value"));
+ return StringUtils.defaultIfBlank(paramObj.getString("value"), defaultValue);
+ }
+
+ /**
+ * The build number of the parent build that was deflaked.
+ *
+ * @return build number of the parent build
+ */
+ @CheckForNull
+ public Integer getParentBuildNumber() {
+ return parentBuildNumber;
}
}
diff --git a/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeCause.java b/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeCause.java
index 7216630..38f047c 100644
--- a/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeCause.java
+++ b/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeCause.java
@@ -23,7 +23,6 @@
* @author Qingzhou Luo
*/
public class DeflakeCause extends Cause.UpstreamCause {
-
/**
* DeflakeCause constructor.
* @param up upstream failing build which is being deflaked
diff --git a/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeListener.java b/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeListener.java
index 0130ea1..c769250 100644
--- a/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeListener.java
+++ b/src/main/java/com/google/jenkins/flakyTestHandler/plugin/deflake/DeflakeListener.java
@@ -26,10 +26,16 @@
import java.util.logging.Logger;
import hudson.Extension;
+import hudson.model.AbstractBuild;
+import hudson.Launcher;
+import hudson.model.AbstractBuild;
+import hudson.model.BuildListener;
import hudson.model.Action;
import hudson.model.Cause;
+import hudson.model.Environment;
import hudson.model.Run;
import hudson.model.TaskListener;
+import hudson.model.Run.RunnerAbortedException;
import hudson.model.listeners.RunListener;
import hudson.tasks.junit.CaseResult;
import hudson.tasks.junit.TestResultAction;
@@ -65,7 +71,7 @@ public void onCompleted(Run run, TaskListener listener) {
if (testResultAction != null && testResultAction.getFailCount() > 0) {
// Only add deflake action if there are test failures
run.addAction(
- new DeflakeAction(getFailingTestClassMethodMap(testResultAction.getFailedTests())));
+ new DeflakeAction(getFailingTestClassMethodMap(testResultAction.getFailedTests()), run));
}
}
@@ -103,4 +109,29 @@ static Map> getFailingTestClassMethodMap(List ca
}
return classMethodMap;
}
+
+ @Override
+ public Environment setUpEnvironment(@SuppressWarnings("rawtypes") AbstractBuild build, Launcher launcher, BuildListener listener)
+ throws IOException, InterruptedException, RunnerAbortedException {
+ AbstractBuild, ?> rootBuild = build.getRootBuild();
+ if (rootBuild == null) {
+ rootBuild = build;
+ }
+
+ final DeflakeAction action = rootBuild.getAction(DeflakeAction.class);
+ if (action == null) {
+ return null;
+ }
+
+ return new Environment() {
+ @Override
+ public void buildEnvVars(Map env) {
+ env.put("DEFLAKE_FAIL_TEST", action.generateMavenTestParams());
+ Integer parentBuildNumber = action.getParentBuildNumber();
+ if (parentBuildNumber != null) {
+ env.put("DEFLAKE_BUILD_NUMBER", parentBuildNumber.toString());
+ }
+ }
+ };
+ }
}