diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml
index 72976b17..87e3c4c7 100644
--- a/checkstyle-suppressions.xml
+++ b/checkstyle-suppressions.xml
@@ -12,4 +12,6 @@
+
diff --git a/src/main/java/com/sonyericsson/jenkins/plugins/bfa/BuildFailureScanner.java b/src/main/java/com/sonyericsson/jenkins/plugins/bfa/BuildFailureScanner.java
index 512cdffd..e8166993 100644
--- a/src/main/java/com/sonyericsson/jenkins/plugins/bfa/BuildFailureScanner.java
+++ b/src/main/java/com/sonyericsson/jenkins/plugins/bfa/BuildFailureScanner.java
@@ -50,6 +50,7 @@
import hudson.tasks.test.AbstractTestResultAction;
import hudson.tasks.test.TestResult;
import jenkins.model.Jenkins;
+import org.apache.commons.lang.StringUtils;
import javax.annotation.Nonnull;
import java.io.BufferedReader;
@@ -252,6 +253,10 @@ public static void scan(Run build, PrintStream scanLog) {
notifySlackAllFail = true;
}
+ if (PluginImpl.getInstance().isBuildDescriptionEnabled() && !foundCauseList.isEmpty()) {
+ build.setDescription(generateDescriptionString(build, foundCauseList));
+ }
+
StatisticsLogger.getInstance().log(build, foundCauseListToLog);
// Check slack plugin is installed
@@ -649,4 +654,47 @@ private static List findFailedTests(final Run build, final Pr
return failedTestList;
}
+
+ /**
+ * Generate text that can be used for the build description using categories and failure causes.
+ *
+ * @param build to get current build description
+ * @param foundCauseList list of failure causes
+ * @return A String of the BFA categories and causes appended to the build's description.
+ */
+ public static String generateDescriptionString(Run build, List foundCauseList) {
+ StringBuffer buildDescription = new StringBuffer();
+ buildDescription.append("");
+
+ if (foundCauseList.get(0) != null) {
+
+ for (int j = 0; j < foundCauseList.get(0).getCategories().size(); j++) {
+ buildDescription.append("");
+ buildDescription.append(foundCauseList.get(0).getCategories().get(j));
+ buildDescription.append(" ");
+ }
+ if (foundCauseList.get(0).getCategories().size() > 0) {
+ buildDescription.append(": ");
+ }
+ }
+
+ // Append all failure causes.
+ if (foundCauseList.get(0) != null) {
+ for (int i = 0; i < foundCauseList.size(); i++) {
+ buildDescription.append("");
+ buildDescription.append(foundCauseList.get(i).getDescription());
+ buildDescription.append("");
+ if (i < (foundCauseList.size() - 1)) {
+ buildDescription.append(" ");
+ }
+ }
+ }
+ buildDescription.append("");
+
+ // Append this build description to any pre-existing build description
+ if (StringUtils.isNotEmpty(build.getDescription())) {
+ buildDescription.insert(0, (build.getDescription().concat("
\n")));
+ }
+ return buildDescription.toString();
+ }
}
diff --git a/src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java b/src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java
index 19aff29e..4832a244 100644
--- a/src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java
+++ b/src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java
@@ -161,6 +161,7 @@ public class PluginImpl extends GlobalConfiguration {
private int nrOfScanThreads;
private int maxLogSize;
+ private boolean buildDescriptionEnabled;
private Boolean graphsEnabled;
@@ -680,6 +681,25 @@ public int getMaxLogSize() {
}
+ /**
+ * Set option to append failure causes to job's build description.
+ *
+ * @param buildDescriptionEnabled should build description option be turned on
+ */
+ @DataBoundSetter
+ public void setBuildDescriptionEnabled(boolean buildDescriptionEnabled) {
+ this.buildDescriptionEnabled = buildDescriptionEnabled;
+ }
+
+ /**
+ * If buildDescriptionEnabled is enabled or not. Build Descriptions will be set to a concatenated
+ * list of the failure descriptions as a convenience.
+ * @return True if enabled.
+ */
+ public boolean isBuildDescriptionEnabled() {
+ return buildDescriptionEnabled;
+ }
+
/**
* Checks if the build with certain result should be analyzed or not.
*
diff --git a/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/PluginImpl/config.jelly b/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/PluginImpl/config.jelly
index b4a9dca0..2a9b6129 100644
--- a/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/PluginImpl/config.jelly
+++ b/src/main/resources/com/sonyericsson/jenkins/plugins/bfa/PluginImpl/config.jelly
@@ -96,5 +96,10 @@
+
+
+
diff --git a/src/test/java/com/sonyericsson/jenkins/plugins/bfa/BuildFailureScannerHudsonTest.java b/src/test/java/com/sonyericsson/jenkins/plugins/bfa/BuildFailureScannerHudsonTest.java
index 92b8975f..eb5ac21c 100644
--- a/src/test/java/com/sonyericsson/jenkins/plugins/bfa/BuildFailureScannerHudsonTest.java
+++ b/src/test/java/com/sonyericsson/jenkins/plugins/bfa/BuildFailureScannerHudsonTest.java
@@ -104,6 +104,7 @@ public class BuildFailureScannerHudsonTest {
private static final String BUILD_LOG = "ERROR: brief\n detail\n";
private static final String BUILD_LOG_FIRST_LINE = "ERROR: brief";
+ private static final String BUILD_DESCRIPTION = "This is a build description.";
private static final String DESCRIPTION = "The error was: ${1,1}${2,1}";
private static final String REGEX = "ERROR: (.*?)$";
private static final String MULTILINE_REGEX = "ERROR: (.*?)$.*? detail";
@@ -1031,6 +1032,86 @@ public boolean perform(AbstractBuild, ?> build, Launcher launcher,
assertEquals("Amount of failure causes does not match.", 0, causeListFromAction.size());
}
+ /**
+ * Test buildDescriptionEnabled = false does not append failure cause to build description.
+ *
+ * @throws Exception if a build description is appended when the setting is set to false.
+ */
+ @Test
+ public void testTestBuildDescriptionEnabledIfDisabled() throws Exception {
+ PluginImpl.getInstance().setTestResultParsingEnabled(true);
+ PluginImpl.getInstance().setBuildDescriptionEnabled(false);
+ FreeStyleProject project = jenkins.createFreeStyleProject();
+
+ project.getBuildersList().add(new PrintToLogBuilder(BUILD_LOG));
+ project.getBuildersList().add(new TestBuilder() {
+ public boolean perform(AbstractBuild, ?> build, Launcher launcher,
+ BuildListener listener) throws InterruptedException, IOException {
+ build.getWorkspace().child("junit.xml").copyFrom(
+ this.getClass().getResource("junit.xml"));
+ return true;
+ }
+ });
+
+ project.getPublishersList().add(new JUnitResultArchiver("junit.xml", false, null));
+
+ QueueTaskFuture future = project.scheduleBuild2(0, new Cause.UserIdCause());
+ FreeStyleBuild build = future.get(10, TimeUnit.SECONDS);
+ jenkins.assertBuildStatus(Result.UNSTABLE, build);
+
+ FailureCauseBuildAction action = build.getAction(FailureCauseBuildAction.class);
+ assertNotNull(action);
+
+ List causeListFromAction = action.getFoundFailureCauses();
+ assertEquals("Amount of failure causes does not match.", 2, causeListFromAction.size());
+
+ // Start with some build description not assigned by BFA and run another scan.
+ action.getFoundFailureCauses();
+ assertEquals(build.getDescription(), null);
+ }
+
+ /**
+ * Test buildDescriptionEnabled = true does append failure cause to existing build description.
+ * with categories set
+ *
+ * @throws Exception if description is not appended correctly.
+ */
+ @Test
+ public void testTestBuildDescriptionEnabledWithCategoriesIfEnabled() throws Exception {
+ PluginImpl.getInstance().setTestResultParsingEnabled(true);
+ PluginImpl.getInstance().setBuildDescriptionEnabled(true);
+ String categories = "foo bar";
+ PluginImpl.getInstance().setTestResultCategories(categories);
+ FreeStyleProject project = jenkins.createFreeStyleProject();
+
+ // Test with a preset build description
+ project.getBuildersList().add(new PrintToLogBuilder(BUILD_LOG));
+ project.getBuildersList().add(new TestBuilder() {
+ public boolean perform(AbstractBuild, ?> build, Launcher launcher,
+ BuildListener listener) throws InterruptedException, IOException {
+ build.getWorkspace().child("junit.xml").copyFrom(this.getClass().getResource("junit.xml"));
+ build.setDescription("Hello World");
+ return true;
+ }
+ });
+
+ project.getPublishersList().add(new JUnitResultArchiver("junit.xml", false, null));
+
+ QueueTaskFuture future = project.scheduleBuild2(0, new Cause.UserIdCause());
+ FreeStyleBuild build = future.get(10, TimeUnit.SECONDS);
+ jenkins.assertBuildStatus(Result.UNSTABLE, build);
+
+ FailureCauseBuildAction action = build.getAction(FailureCauseBuildAction.class);
+ assertNotNull(action);
+
+ List causeListFromAction = action.getFoundFailureCauses();
+ assertEquals("Amount of failure causes does not match.", 2, causeListFromAction.size());
+
+ String testDescription = "Hello World
\n"
+ + "foo bar : Here are details of the failure... More details";
+ assertEquals(build.getDescription(), testDescription);
+ }
+
/**
* ArgumentMatcher for a Statistics object.
*/
diff --git a/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-local-expected.yml b/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-local-expected.yml
index 5990751a..33db670d 100644
--- a/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-local-expected.yml
+++ b/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-local-expected.yml
@@ -1,3 +1,4 @@
+buildDescriptionEnabled: false
doNotAnalyzeAbortedJob: true
gerritTriggerEnabled: true
globalEnabled: true
diff --git a/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-mongo-expected.yml b/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-mongo-expected.yml
index 4f30360b..bce219db 100644
--- a/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-mongo-expected.yml
+++ b/src/test/resources/com/sonyericsson/jenkins/plugins/bfa/jcasc/jcasc-mongo-expected.yml
@@ -1,3 +1,4 @@
+buildDescriptionEnabled: false
doNotAnalyzeAbortedJob: true
gerritTriggerEnabled: true
globalEnabled: true