Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: jenkinsci/build-failure-analyzer-plugin
...
head fork: jenkinsci/build-failure-analyzer-plugin
compare: build-failure-analyzer-1.3.0
  • 9 commits
  • 24 files changed
  • 0 commit comments
  • 4 contributors
Commits on Nov 22, 2012
@rsandell rsandell [maven-release-plugin] prepare for next development iteration 5d7a73c
Commits on Nov 23, 2012
ACH Fixed image URLs for Jenkins instances which are not running under th…
…e root URL
fc064e4
Marie Lennerhagen Enable testing of pattern on a text
This patch makes it possible to verify that a pattern, supplied
for a build log indication, matches a line of text entered by
the user.

Change-Id: Icf6167c722beee87a9abad64ec649f10be2452f2
3e664e5
Commits on Nov 26, 2012
@TWestling TWestling Merge pull request #1 from christianapel/master
Sending a pull request
ebd1f0a
@rsandell rsandell Merge branch 'master' of github.com:jenkinsci/build-failure-analyzer-…
…plugin
8dfc33b
@TWestling TWestling Restructured resource handling.
Changed how the plugin loads its icons so
that the icon for the the different icons is loaded
in the same way as the icon for the FailureCauseBuildAction.

Change-Id: I395f6819e28df5cd124d199389fe286876547757
deeef45
Commits on Dec 04, 2012
@TWestling TWestling Changed method for adding text to the log
Changed to using an annotator to fix problems
with other annotators, namely the TimeStamper plugin.

Change-Id: I2952358d233edfd0afa95cc90672113db75df7f4
04f8cbc
Commits on Dec 06, 2012
@rsandell rsandell Converted the post build step to a RunListener
So that it can work better on core versions > 1.463
The scannerJobProperty is now in charge of aggregating
to matrix main build.

Change-Id: If27a29e71880c0ed61f82b30808b231fa0323e3e
df8e8f0
@rsandell rsandell [maven-release-plugin] prepare release build-failure-analyzer-1.3.0 8a10e7a
Showing with 642 additions and 333 deletions.
  1. +13 −11 pom.xml
  2. +89 −0 src/main/java/com/sonyericsson/jenkins/plugins/bfa/AnnotationHelper.java
  3. +50 −62 src/main/java/com/sonyericsson/jenkins/plugins/bfa/{FailureScanner.java → BuildFailureScanner.java}
  4. +0 −61 src/main/java/com/sonyericsson/jenkins/plugins/bfa/FailureScannerProvisioner.java
  5. +101 −0 src/main/java/com/sonyericsson/jenkins/plugins/bfa/IndicationAnnotator.java
  6. +65 −0 src/main/java/com/sonyericsson/jenkins/plugins/bfa/IndicationAnnotatorFactory.java
  7. +25 −5 src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java
  8. +2 −2 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseBuildAction.java
  9. +0 −28 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/FoundFailureCause.java
  10. +92 −0 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/ScannerJobProperty.java
  11. +9 −16 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/ScannerOffJobProperty.java
  12. +26 −0 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndication.java
  13. +0 −78 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/indication/FoundIndication.java
  14. +2 −2 src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/index.groovy
  15. +4 −1 src/main/resources/com/sonyericsson/jenkins/plugins/bfa/Messages.properties
  16. +1 −1  src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseBuildAction/summary.jelly
  17. +1 −1  src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseMatrixBuildAction/summary.jelly
  18. 0  ...s/com/sonyericsson/jenkins/plugins/bfa/model/{ScannerOffJobProperty → ScannerJobProperty}/config.jelly
  19. 0  ...onyericsson/jenkins/plugins/bfa/model/{ScannerOffJobProperty → ScannerJobProperty}/help-doNotScan.html
  20. +9 −0 src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndication/config.jelly
  21. +1 −0  src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndication/help-testText.html
  22. +0 −41 src/main/resources/com/sonyericsson/jenkins/plugins/bfa/model/indication/FoundIndication/index.jelly
  23. +127 −24 ...va/com/sonyericsson/jenkins/plugins/bfa/{FailureScannerTest.java → BuildFailureScannerHudsonTest.java}
  24. +25 −0 src/test/java/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndicationTest.java
View
24 pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.sonyericsson.jenkins.plugins.bfa</groupId>
<artifactId>build-failure-analyzer</artifactId>
- <version>1.2.0</version>
+ <version>1.3.0</version>
<packaging>hpi</packaging>
<name>Build Failure Analyzer</name>
<description>Jenkins Build Failure Analyzer Plugin</description>
@@ -82,7 +82,7 @@
<dependency>
<groupId>com.sonyericsson.hudson.plugins.gerrit</groupId>
<artifactId>gerrit-trigger</artifactId>
- <version>2.6.0</version>
+ <version>2.7.0</version>
<optional>true</optional>
<exclusions>
<exclusion>
@@ -160,15 +160,6 @@
</dependency>
</dependencies>
<build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>cobertura-maven-plugin</artifactId>
- <version>2.4</version>
- </plugin>
- </plugins>
- </pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -185,6 +176,17 @@
<target>1.6</target>
</configuration>
</plugin>
+ <!-- Uncomment to change contextPath -->
+ <!--plugin>
+ <groupId>org.jenkins-ci.tools</groupId>
+ <artifactId>maven-hpi-plugin</artifactId>
+ <version>1.74</version>
+ <extensions>true</extensions>
+ <configuration>
+ <showDeprecation>true</showDeprecation>
+ <contextPath>/hudson</contextPath>
+ </configuration>
+ </plugin-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
View
89 src/main/java/com/sonyericsson/jenkins/plugins/bfa/AnnotationHelper.java
@@ -0,0 +1,89 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
+ *
+ * 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.sonyericsson.jenkins.plugins.bfa;
+
+/**
+ * Helper for annotating the lines, creates the strings to annotate with.
+ *
+ * @author Tomas Westling&lt;tomas.westling@sonymobile.com&gt;
+ */
+public class AnnotationHelper {
+
+ private String before = "";
+ private String after = "";
+ private String title = "";
+
+ /**
+ * Gets the String to annotate with before the console text.
+ *
+ * @return the String to put before the console text.
+ */
+ public String getBefore() {
+ if (!title.isEmpty()) {
+ return before + "<span style=\"color:white;background:red\" title=\"" + title + "\">";
+ } else {
+ return before;
+ }
+ }
+
+ /**
+ * Gets the String to annotate with after the console text.
+ *
+ * @return the String to put after the console text.
+ */
+ public String getAfter() {
+ return after;
+ }
+
+ /**
+ * Adds a focus id line before the console text.
+ *
+ * @param id the id for the line, to refer to in links.
+ */
+ public void addFocus(String id) {
+ this.before += "<span id=\"" + id + "\">";
+ }
+
+ /**
+ * Adds a title for the line.
+ *
+ * @param addedTitle the title of the line.
+ */
+ public void addTitle(String addedTitle) {
+ if (this.title.equals("")) {
+ this.title = addedTitle;
+ } else {
+ this.title += "\n" + addedTitle;
+ }
+ }
+
+ /**
+ * Adds a String to annotate with, after the console text.
+ *
+ * @param addedAfter the String to put after the console text.
+ */
+ public void addAfter(String addedAfter) {
+ this.after += addedAfter;
+ }
+}
View
112 ...n/jenkins/plugins/bfa/FailureScanner.java → ...kins/plugins/bfa/BuildFailureScanner.java
@@ -29,23 +29,18 @@
import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
import com.sonyericsson.jenkins.plugins.bfa.model.FailureReader;
import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
+import com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication;
import com.sonyericsson.jenkins.plugins.bfa.statistics.StatisticsLogger;
-import hudson.Launcher;
-import hudson.matrix.MatrixAggregatable;
-import hudson.matrix.MatrixAggregator;
-import hudson.matrix.MatrixBuild;
+import hudson.Extension;
+import hudson.matrix.MatrixProject;
import hudson.model.AbstractBuild;
-import hudson.model.AbstractProject;
-import hudson.model.BuildListener;
-import hudson.model.Hudson;
import hudson.model.Result;
-import hudson.tasks.BuildStepDescriptor;
-import hudson.tasks.BuildStepMonitor;
-import hudson.tasks.Notifier;
-import hudson.tasks.Publisher;
+import hudson.model.TaskListener;
+import hudson.model.listeners.RunListener;
+import java.io.IOException;
import java.io.PrintStream;
import java.util.Collection;
import java.util.Collections;
@@ -62,36 +57,55 @@
*
* @author Tomas Westling &lt;thomas.westling@sonyericsson.com&gt;
*/
-public class FailureScanner extends Notifier implements MatrixAggregatable {
+@Extension(ordinal = BuildFailureScanner.ORDINAL)
+public class BuildFailureScanner extends RunListener<AbstractBuild> {
- private static final Logger logger = Logger.getLogger(FailureScanner.class.getName());
+ /**
+ * The ordinal of this extension, one thousand below the GerritTrigger plugin.
+ */
+ public static final int ORDINAL = 11003;
+ private static final Logger logger = Logger.getLogger(BuildFailureScanner.class.getName());
@Override
- public boolean needsToRunAfterFinalized() {
- return true;
+ public void onStarted(AbstractBuild build, TaskListener listener) {
+ if (PluginImpl.shouldScan(build)
+ && build.getProject().getProperty(ScannerJobProperty.class) == null) {
+ try {
+ build.getProject().addProperty(new ScannerJobProperty(false));
+ } catch (IOException e) {
+ logger.log(Level.WARNING, "Failed to add a ScannerJobProperty to "
+ + build.getProject().getFullDisplayName(), e);
+ listener.getLogger().println("[BFA] WARNING! Failed to add the scanner property to this job.");
+ }
+ }
}
@Override
- public BuildStepMonitor getRequiredMonitorService() {
- return BuildStepMonitor.NONE;
+ public void onCompleted(AbstractBuild build, TaskListener listener) {
+ logger.entering(getClass().getName(), "onCompleted");
+ if (build.getResult().isWorseThan(Result.SUCCESS) && PluginImpl.shouldScan(build)
+ && !(build.getProject() instanceof MatrixProject)) {
+ scan(build, listener.getLogger());
+ }
}
- @Override
- public boolean perform(AbstractBuild build, final Launcher launcher, final BuildListener buildListener) {
- if (PluginImpl.shouldScan(build) && build.getResult().isWorseThan(Result.SUCCESS)) {
- try {
- PrintStream buildLog = buildListener.getLogger();
- Collection<FailureCause> causes = PluginImpl.getInstance().getKnowledgeBase().getCauses();
- List<FoundFailureCause> foundCauseList = findCauses(causes, build, buildLog);
- FailureCauseBuildAction buildAction = new FailureCauseBuildAction(foundCauseList);
- build.addAction(buildAction);
- StatisticsLogger.getInstance().log(build, foundCauseList);
- } catch (Exception e) {
- logger.log(Level.SEVERE, "Could not get the causes from the knowledge base", e);
- return false;
- }
+ /**
+ * Performs a scan of the build, adds the {@link FailureCauseBuildAction} and reports to the
+ * {@link StatisticsLogger}.
+ *
+ * @param build the build to scan
+ * @param buildLog log to write information to.
+ */
+ public static void scan(AbstractBuild build, PrintStream buildLog) {
+ try {
+ Collection<FailureCause> causes = PluginImpl.getInstance().getKnowledgeBase().getCauses();
+ List<FoundFailureCause> foundCauseList = findCauses(causes, build, buildLog);
+ FailureCauseBuildAction buildAction = new FailureCauseBuildAction(foundCauseList);
+ build.addAction(buildAction);
+ StatisticsLogger.getInstance().log(build, foundCauseList);
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "Could not scan build " + build, e);
}
- return true;
}
/**
@@ -102,8 +116,8 @@ public boolean perform(AbstractBuild build, final Launcher launcher, final Build
* @param buildLog the build log.
* @return a list of found failure causes.
*/
- private List<FoundFailureCause> findCauses(final Collection<FailureCause> causes,
- final AbstractBuild build, final PrintStream buildLog) {
+ private static List<FoundFailureCause> findCauses(final Collection<FailureCause> causes,
+ final AbstractBuild build, final PrintStream buildLog) {
final List<FoundFailureCause> foundFailureCauseList =
Collections.synchronizedList(new LinkedList<FoundFailureCause>());
long start = System.currentTimeMillis();
@@ -153,7 +167,7 @@ public void run() {
* @param buildLog the build log.
* @return a list of found indications for a cause.
*/
- private List<FoundIndication> findIndications(FailureCause cause, AbstractBuild build, PrintStream buildLog) {
+ private static List<FoundIndication> findIndications(FailureCause cause, AbstractBuild build, PrintStream buildLog) {
long start = System.currentTimeMillis();
List<Indication> indicationList = cause.getIndications();
List<FoundIndication> foundIndicationList = new LinkedList<FoundIndication>();
@@ -180,34 +194,8 @@ public void run() {
* @param buildLog the build log.
* @return an indication if one is found, null otherwise.
*/
- private FoundIndication findIndication(Indication indication, AbstractBuild build, PrintStream buildLog) {
+ private static FoundIndication findIndication(Indication indication, AbstractBuild build, PrintStream buildLog) {
FailureReader failureReader = indication.getReader();
return failureReader.scan(build, buildLog);
}
-
- @Override
- public FailureScannerDescriptor getDescriptor() {
- return Hudson.getInstance().getDescriptorByType(FailureScannerDescriptor.class);
- }
-
- @Override
- public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
- return new FailureCauseMatrixAggregator(build, launcher, listener);
- }
-
- /**
- * Descriptor, apparently needed for the FailureScannerTest in order to add this notifier to the build.
- */
- public static final class FailureScannerDescriptor extends BuildStepDescriptor<Publisher> {
-
- @Override
- public String getDisplayName() {
- return "";
- }
-
- @Override
- public boolean isApplicable(Class<? extends AbstractProject> aClass) {
- return true;
- }
- }
}
View
61 src/main/java/com/sonyericsson/jenkins/plugins/bfa/FailureScannerProvisioner.java
@@ -1,61 +0,0 @@
-/*
- * The MIT License
- *
- * Copyright 2012 Sony Ericsson Mobile Communications. All rights reserved.
- * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
- *
- * 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.sonyericsson.jenkins.plugins.bfa;
-
-import hudson.Extension;
-import hudson.model.AbstractBuild;
-import hudson.model.TaskListener;
-import hudson.model.listeners.RunListener;
-
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * A RunListener that puts the {@link FailureScanner} into all builds.
- *
- * @author Robert Sandell &lt;robert.sandell@sonyericsson.com&gt;
- */
-@Extension
-public class FailureScannerProvisioner extends RunListener<AbstractBuild> {
-
- private static final Logger logger = Logger.getLogger(FailureScannerProvisioner.class.getName());
-
- @Override
- public void onStarted(AbstractBuild build, TaskListener listener) {
- if (PluginImpl.shouldScan(build)
- && build.getProject().getPublishersList().get(FailureScanner.class) == null) {
- try {
- build.getProject().getPublishersList().add(new FailureScanner());
- } catch (IOException e) {
- logger.log(Level.WARNING, "Failed to add a FailureScanner to "
- + build.getProject().getFullDisplayName(), e);
- listener.getLogger().println("[BFA] WARNING! Failed to add the scanner to this job, "
- + "failure analysis will not be performed.");
- }
- }
- }
-}
View
101 src/main/java/com/sonyericsson/jenkins/plugins/bfa/IndicationAnnotator.java
@@ -0,0 +1,101 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
+ *
+ * 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.sonyericsson.jenkins.plugins.bfa;
+
+import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
+import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
+import hudson.MarkupText;
+import hudson.console.ConsoleAnnotator;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Annotates the build log so that we can create links to it and mark found
+ * indications.
+ *
+ * @author Tomas Westling &lt;tomas.westling@sonymobile.com&gt;
+ */
+public class IndicationAnnotator extends ConsoleAnnotator<Object> {
+
+ private int currentLine;
+ /**
+ * The number of lines to show above the found Indication
+ */
+ private static final int CONTEXT = 10;
+ private Map<Integer, AnnotationHelper> helperMap;
+
+ /**
+ * Standard constructor.
+ *
+ * @param foundFailureCauses the {@link FoundFailureCause}s to add annotation for.
+ */
+ public IndicationAnnotator(List<FoundFailureCause> foundFailureCauses) {
+ helperMap = new HashMap<Integer, AnnotationHelper>();
+ for (FoundFailureCause foundFailureCause : foundFailureCauses) {
+ addToHelperMap(foundFailureCause);
+ }
+ currentLine = 0;
+ }
+
+ /**
+ * Adds the matching and focus lines to the helper map, to ease annotating later.
+ *
+ * @param cause the {@link FoundFailureCause}} to add lines for.
+ */
+ private void addToHelperMap(FoundFailureCause cause) {
+ for (FoundIndication indication : cause.getIndications()) {
+ int matchingLine = indication.getMatchingLine();
+ int focusLine = matchingLine - CONTEXT;
+ if (focusLine < 1) {
+ focusLine = 1;
+ }
+ AnnotationHelper matchingHelper = helperMap.get(matchingLine);
+ if (matchingHelper == null) {
+ matchingHelper = new AnnotationHelper();
+ matchingHelper.addAfter("</span>");
+ }
+ matchingHelper.addTitle(cause.getName());
+ helperMap.put(matchingLine, matchingHelper);
+ AnnotationHelper focusHelper = helperMap.get(focusLine);
+ if (focusHelper == null) {
+ focusHelper = new AnnotationHelper();
+ }
+ focusHelper.addFocus(matchingLine + cause.getId());
+ focusHelper.addAfter("</span>");
+ helperMap.put(focusLine, focusHelper);
+ }
+ }
+
+ @Override
+ public ConsoleAnnotator annotate(Object context, MarkupText text) {
+ currentLine++;
+ AnnotationHelper match = helperMap.get(currentLine);
+ if (match != null) {
+ text.wrapBy(match.getBefore(), match.getAfter());
+ }
+ return this;
+ }
+}
View
65 src/main/java/com/sonyericsson/jenkins/plugins/bfa/IndicationAnnotatorFactory.java
@@ -0,0 +1,65 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
+ *
+ * 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.sonyericsson.jenkins.plugins.bfa;
+
+import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
+import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
+import hudson.Extension;
+import hudson.console.ConsoleAnnotator;
+import hudson.console.ConsoleAnnotatorFactory;
+import hudson.model.AbstractBuild;
+import org.kohsuke.stapler.Ancestor;
+import org.kohsuke.stapler.Stapler;
+import org.kohsuke.stapler.StaplerRequest;
+
+import java.util.List;
+
+/**
+ * Factory for creating a new {@link IndicationAnnotator} when the log should be annotated.
+ *
+ * @author Tomas Westling &lt;tomas.westling@sonymobile.com&gt;
+ */
+@Extension
+public class IndicationAnnotatorFactory extends ConsoleAnnotatorFactory {
+
+ @Override
+ public ConsoleAnnotator newInstance(Object context) {
+ StaplerRequest currentRequest = Stapler.getCurrentRequest();
+ Ancestor ancestor = currentRequest.findAncestor(AbstractBuild.class);
+ if (ancestor == null) {
+ return null;
+ }
+ Object object = ancestor.getObject();
+ AbstractBuild build = (AbstractBuild)object;
+ FailureCauseBuildAction action = build.getAction(FailureCauseBuildAction.class);
+ if (action == null) {
+ return null;
+ }
+ List<FoundFailureCause> foundFailureCauses = action.getFoundFailureCauses();
+ if (foundFailureCauses.size() < 1) {
+ return null;
+ }
+ return new IndicationAnnotator(foundFailureCauses);
+ }
+}
View
30 src/main/java/com/sonyericsson/jenkins/plugins/bfa/PluginImpl.java
@@ -28,7 +28,7 @@
import com.sonyericsson.jenkins.plugins.bfa.db.KnowledgeBase;
import com.sonyericsson.jenkins.plugins.bfa.db.LocalFileKnowledgeBase;
import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
-import com.sonyericsson.jenkins.plugins.bfa.model.ScannerOffJobProperty;
+import com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty;
import hudson.ExtensionList;
import hudson.Plugin;
import hudson.PluginManager;
@@ -41,6 +41,7 @@
import hudson.security.PermissionGroup;
import hudson.util.CopyOnWriteList;
import net.sf.json.JSONObject;
+import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import java.io.IOException;
@@ -196,6 +197,25 @@ public static String getImageUrl(String size, String name) {
}
/**
+ * Get the full url to an image, including rootUrl and context path.
+ *
+ * @param size the size of the image (the sub directory of images).
+ * @param name the name of the image file.
+ * @return a URL to the image.
+ */
+ public static String getFullImageUrl(String size, String name) {
+ String contextPath = "";
+ StaplerRequest currentRequest = Stapler.getCurrentRequest();
+ if (currentRequest != null) {
+ contextPath = currentRequest.getContextPath();
+ }
+ if (contextPath.startsWith("/")) {
+ contextPath = contextPath.substring(1);
+ }
+ return Hudson.getInstance().getRootUrl() + contextPath + getImageUrl(size, name);
+ }
+
+ /**
* Provides a Jenkins relative url to a plugin internal image of {@link #DEFAULT_ICON_SIZE} size.
*
* @param name the name of the image.
@@ -282,7 +302,7 @@ public void setGerritTriggerEnabled(Boolean gerritTriggerEnabled) {
}
/**
- * The number of threads to have in the pool for each build. Used by the {@link FailureScanner}.
+ * The number of threads to have in the pool for each build. Used by the {@link BuildFailureScanner}.
* Will return nothing less than {@link #MINIMUM_NR_OF_SCAN_THREADS}.
*
* @return the number of scan threads.
@@ -296,7 +316,7 @@ public int getNrOfScanThreads() {
/**
- * The number of threads to have in the pool for each build. Used by the {@link FailureScanner}.
+ * The number of threads to have in the pool for each build. Used by the {@link BuildFailureScanner}.
* Will throw an {@link IllegalArgumentException} if the parameter is less than {@link #MINIMUM_NR_OF_SCAN_THREADS}.
*
* @param nrOfScanThreads the number of scan threads.
@@ -310,7 +330,7 @@ public void setNrOfScanThreads(int nrOfScanThreads) {
/**
* Checks if the specified build should be scanned or not. Determined by {@link #isGlobalEnabled()} and if the
- * build's project has {@link com.sonyericsson.jenkins.plugins.bfa.model.ScannerOffJobProperty#isDoNotScan()}.
+ * build's project has {@link com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty#isDoNotScan()}.
*
* @param build the build
* @return true if it should be scanned.
@@ -318,7 +338,7 @@ public void setNrOfScanThreads(int nrOfScanThreads) {
public static boolean shouldScan(AbstractBuild build) {
if (getInstance().isGlobalEnabled()) {
AbstractProject project = build.getProject();
- ScannerOffJobProperty property = (ScannerOffJobProperty)project.getProperty(ScannerOffJobProperty.class);
+ ScannerJobProperty property = (ScannerJobProperty)project.getProperty(ScannerJobProperty.class);
if (property != null) {
return !property.isDoNotScan();
} else {
View
4 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseBuildAction.java
@@ -97,7 +97,7 @@ public String getUrlName() {
* @return the image url.
*/
public String getImageUrl() {
- return PluginImpl.getImageUrl("48x48", PluginImpl.DEFAULT_ICON_NAME);
+ return PluginImpl.getFullImageUrl("48x48", PluginImpl.DEFAULT_ICON_NAME);
}
/**
@@ -106,7 +106,7 @@ public String getImageUrl() {
* @return the image url.
*/
public String getBadgeImageUrl() {
- return PluginImpl.getImageUrl("16x16", PluginImpl.DEFAULT_ICON_NAME);
+ return PluginImpl.getFullImageUrl("16x16", PluginImpl.DEFAULT_ICON_NAME);
}
/**
View
28 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/FoundFailureCause.java
@@ -25,13 +25,9 @@
package com.sonyericsson.jenkins.plugins.bfa.model;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
-import org.kohsuke.stapler.StaplerRequest;
-import org.kohsuke.stapler.StaplerResponse;
import java.util.LinkedList;
import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
/**
* Found Failure Cause of a build.
@@ -44,8 +40,6 @@
private String description;
private List<String> categories;
private List<FoundIndication> indications;
- private static final Logger logger = Logger.getLogger(FoundFailureCause.class.getName());
-
/**
* Standard constructor.
@@ -129,26 +123,4 @@ public void addIndications(List<FoundIndication> foundIndications) {
}
indications.addAll(foundIndications);
}
-
- /**
- * Used when we are directed to a FoundIndication beneath this FoundFailureCause, when looking at
- * an indication.
- * @param token the indication number of this FoundFailureCause.
- * @param req the stapler request.
- * @param resp the stapler response.
- * @return the correct FoundIndication.
- */
- public FoundIndication getDynamic(String token, StaplerRequest req, StaplerResponse resp) {
- try {
- int indicationNumber = Integer.parseInt(token) - 1;
- if (indicationNumber >= 0 && indicationNumber < indications.size()) {
- return indications.get(indicationNumber);
- }
- } catch (NumberFormatException nfe) {
- logger.log(Level.WARNING, "[BFA] Failed to parse token for getDynamic: " + token);
- return null;
- }
- logger.log(Level.WARNING, "[BFA] Unable to navigate to the Indication: " + token);
- return null;
- }
}
View
92 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/ScannerJobProperty.java
@@ -0,0 +1,92 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2012 Sony Mobile Communications AB. All rights reserved.
+ *
+ * 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.sonyericsson.jenkins.plugins.bfa.model;
+
+import com.sonyericsson.jenkins.plugins.bfa.FailureCauseMatrixAggregator;
+import com.sonyericsson.jenkins.plugins.bfa.Messages;
+import hudson.Extension;
+import hudson.Launcher;
+import hudson.matrix.MatrixAggregatable;
+import hudson.matrix.MatrixAggregator;
+import hudson.matrix.MatrixBuild;
+import hudson.model.AbstractProject;
+import hudson.model.BuildListener;
+import hudson.model.JobProperty;
+import hudson.model.JobPropertyDescriptor;
+import org.kohsuke.stapler.DataBoundConstructor;
+
+import java.io.Serializable;
+
+/**
+ * A JobProperty that flags a job that should not be scanned. Also works as the {@link MatrixAggregatable}
+ *
+ * @author Robert Sandell &lt;robert.sandell@sonymobile.com&gt;
+ */
+public class ScannerJobProperty extends JobProperty<AbstractProject<?, ?>> implements MatrixAggregatable, Serializable {
+
+ private boolean doNotScan;
+
+ /**
+ * Standard DataBound Constructor.
+ *
+ * @param doNotScan signal that builds of this job should not be scanned.
+ */
+ @DataBoundConstructor
+ public ScannerJobProperty(boolean doNotScan) {
+ this.doNotScan = doNotScan;
+ }
+
+ /**
+ * Default Constructor. <strong>Do not use unless you are a serializer!</strong>
+ */
+ public ScannerJobProperty() {
+ }
+
+ /**
+ * The value. True turns the scanner off.
+ *
+ * @return if no scan should be done.
+ */
+ public boolean isDoNotScan() {
+ return doNotScan;
+ }
+
+ @Override
+ public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
+ return new FailureCauseMatrixAggregator(build, launcher, listener);
+ }
+
+ /**
+ * Descriptor for {@link ScannerJobProperty}.
+ */
+ @Extension
+ public static class ScannerJobPropertyDescriptor extends JobPropertyDescriptor {
+
+ @Override
+ public String getDisplayName() {
+ return Messages.ScannerJobProperty_DisplayName();
+ }
+ }
+}
View
25 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/ScannerOffJobProperty.java
@@ -24,12 +24,8 @@
package com.sonyericsson.jenkins.plugins.bfa.model;
-import com.sonyericsson.jenkins.plugins.bfa.Messages;
-import hudson.Extension;
import hudson.model.AbstractProject;
import hudson.model.JobProperty;
-import hudson.model.JobPropertyDescriptor;
-import org.kohsuke.stapler.DataBoundConstructor;
import java.io.Serializable;
@@ -37,23 +33,23 @@
* A JobProperty that flags a job that should not be scanned.
*
* @author Robert Sandell &lt;robert.sandell@sonyericsson.com&gt;
+ * @deprecated {@link ScannerJobProperty} is used instead, but this is kept to be able to de-serialize old jobs.
*/
+@Deprecated
public class ScannerOffJobProperty extends JobProperty<AbstractProject<?, ?>> implements Serializable {
private boolean doNotScan;
/**
- * Standard DataBound Constructor.
+ * Standard Constructor.
*
* @param doNotScan signal that builds of this job should not be scanned.
*/
- @DataBoundConstructor
public ScannerOffJobProperty(boolean doNotScan) {
this.doNotScan = doNotScan;
}
/**
- * Default Constructor.
- * <strong>Do not use unless you are a serializer!</strong>
+ * Default Constructor. <strong>Do not use unless you are a serializer!</strong>
*/
public ScannerOffJobProperty() {
}
@@ -68,14 +64,11 @@ public boolean isDoNotScan() {
}
/**
- * Descriptor for {@link ScannerOffJobProperty}.
+ * De-serialize this object to a {@link ScannerJobProperty}.
+ *
+ * @return an instance of {@link ScannerJobProperty} with the same data.
*/
- @Extension
- public static class ScannerOffJobPropertyDescriptor extends JobPropertyDescriptor {
-
- @Override
- public String getDisplayName() {
- return Messages.ScannerOffJobProperty_DisplayName();
- }
+ public Object readResolve() {
+ return new ScannerJobProperty(doNotScan);
}
}
View
26 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndication.java
@@ -29,7 +29,10 @@
import com.sonyericsson.jenkins.plugins.bfa.model.FailureReader;
import hudson.Extension;
import hudson.model.Hudson;
+import hudson.util.FormValidation;
+import java.util.regex.PatternSyntaxException;
import org.kohsuke.stapler.DataBoundConstructor;
+import org.kohsuke.stapler.QueryParameter;
/**
* Indication that parses the build log file for a pattern.
@@ -74,5 +77,28 @@ public IndicationDescriptor getDescriptor() {
public String getDisplayName() {
return Messages.BuildLogIndication_DisplayName();
}
+
+ /**
+ * Tests if a string matches a pattern.
+ * @param testPattern the pattern.
+ * @param testText the string.
+ * @return {@link FormValidation#ok(java.lang.String) } if the pattern is valid and
+ * the string matches the pattern,
+ * {@link FormValidation#warning(java.lang.String) } if the pattern is valid and
+ * the string does not match the pattern,
+ * {@link FormValidation#error(java.lang.String) } otherwise.
+ */
+ public FormValidation doMatchText(
+ @QueryParameter("pattern") final String testPattern,
+ @QueryParameter("testText") final String testText) {
+ try {
+ if (testText.matches(testPattern)) {
+ return FormValidation.ok(Messages.StringMatchesPattern());
+ }
+ return FormValidation.warning(Messages.StringDoesNotMatchPattern());
+ } catch (PatternSyntaxException e) {
+ return FormValidation.error(Messages.InvalidPattern_Error());
+ }
+ }
}
}
View
78 src/main/java/com/sonyericsson/jenkins/plugins/bfa/model/indication/FoundIndication.java
@@ -24,18 +24,8 @@
package com.sonyericsson.jenkins.plugins.bfa.model.indication;
-import hudson.MarkupText;
import hudson.model.AbstractBuild;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
/**
* Found Indication of an unsuccessful build.
*
@@ -51,11 +41,6 @@
private int matchingLine;
private String pattern;
private AbstractBuild build;
- /**
- * The number of lines to show above the found Indication
- */
- private static final int CONTEXT = 10;
- private static final Logger logger = Logger.getLogger(FoundIndication.class.getName());
/**
* Standard constructor.
@@ -107,67 +92,4 @@ public String getPattern() {
public AbstractBuild getBuild() {
return build;
}
-
- /**
- * Adds extra information to the log and presents it.
- *
- * @return the log file of this indication, with extra information.
- */
- public String getModifiedLog() {
- StringBuilder builder = new StringBuilder("<pre>");
- String currentLine;
- int currentLineNumber = 1;
- int focusLine;
- if (matchingLine < CONTEXT) {
- focusLine = 1;
- } else {
- focusLine = matchingLine - CONTEXT;
- }
- File rootDir = build.getRootDir();
- File inputFile = new File(rootDir, matchingFile);
- BufferedReader br = null;
- try {
- br = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), FILE_ENCODING));
- while ((currentLine = br.readLine()) != null) {
- MarkupText markup = new MarkupText(currentLine);
- currentLine = markup.toString(true);
- if (currentLineNumber == focusLine) {
- //if focusLine and matchingLine both are equal to the first line.
- if (currentLineNumber == matchingLine) {
- builder.append("<span class=\"errorLine\" id=\"focusLine\">");
- builder.append(currentLine);
- builder.append("</span>\n");
- } else {
- builder.append("<span id=\"focusLine\">");
- builder.append(currentLine);
- builder.append("</span>\n");
- }
- } else if (currentLineNumber == matchingLine) {
- builder.append("<span class=\"errorLine\">");
- builder.append(currentLine);
- builder.append("</span>\n");
- } else if (currentLineNumber != focusLine && currentLineNumber != matchingLine) {
- builder.append(currentLine);
- builder.append("\n");
- }
- currentLineNumber++;
- }
- } catch (FileNotFoundException e) {
- logger.log(Level.SEVERE, "[BFA] Could not open reader for build: " + build.getDisplayName()
- + " and Indication: " + pattern, e);
- } catch (IOException e) {
- logger.log(Level.SEVERE, "[BFA] I/O problems during build log modification for build:"
- + build.getDisplayName() + " and Indication: " + pattern, e);
- } finally {
- if (br != null) {
- try {
- br.close();
- } catch (IOException e) {
- logger.log(Level.WARNING, "Failed to close the reader. ", e);
- }
- }
- }
- builder.append("</pre>");
- return builder.toString();
- }
}
View
4 src/main/resources/com/sonyericsson/jenkins/plugins/bfa/CauseManagement/index.groovy
@@ -37,8 +37,8 @@ l.layout(permission: PluginImpl.UPDATE_PERMISSION) {
l.header(title: _("Failure Cause Management - Confirm Remove"))
def management = CauseManagement.getInstance();
- def bgImageUrl = PluginImpl.getImageUrl("256x256", "information.png");
- def newImageUrl = PluginImpl.getImageUrl("24x24", "newinformation.png");
+ def bgImageUrl = PluginImpl.getFullImageUrl("256x256", "information.png");
+ def newImageUrl = PluginImpl.getFullImageUrl("24x24", "newinformation.png");
l.side_panel() {
if (!management.isUnderTest()) {
View
5 src/main/resources/com/sonyericsson/jenkins/plugins/bfa/Messages.properties
@@ -4,8 +4,11 @@ PermissionUpdate_Description=Add and Update Failure causes.
PermissionRemove_Description=Remove Failure causes.
BuildLogIndication_DisplayName=Build Log Indication
CauseManagement_DisplayName=Failure Cause Management
-ScannerOffJobProperty_DisplayName=Do not Scan failed builds
+ScannerJobProperty_DisplayName=Do not Scan failed builds
LocalFileKnowledgeBase_DisplayName=Jenkins Local
MongoDBKnowledgeBase_DisplayName=Mongo DB
MongoDBKnowledgeBase_ConnectionError=Could not connect
MongoDBKnowledgeBase_ConnectionOK=Connection OK!
+StringMatchesPattern=String matches pattern
+StringDoesNotMatchPattern=String does not match pattern
+InvalidPattern_Error=Invalid pattern
View
2  ...esources/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseBuildAction/summary.jelly
@@ -71,7 +71,7 @@
<td/>
<td>
<j:forEach var="indication" items="${cause.getIndications()}" indexVar="indicationNumber">
- <a href="bfa/${causeNumber+1}/${indicationNumber+1}#focusLine">
+ <a href="console#${indication.matchingLine}${cause.id}">
${%Indication} ${indicationNumber+1}
</a>
<st:nbsp/>
View
2  ...es/com/sonyericsson/jenkins/plugins/bfa/model/FailureCauseMatrixBuildAction/summary.jelly
@@ -50,7 +50,7 @@
${failureCause.name}
<j:forEach var="indication" items="${failureCause.getIndications()}"
indexVar="indicationNumber">
- <a href="${run.getParent().getCombination().toString()}/bfa/${failureCauseNumber+1}/${indicationNumber+1}#focusLine">
+ <a href="${run.getParent().getCombination().toString()}/console#${indication.matchingLine}${failureCause.id}">
(${%Indication} ${indicationNumber+1})
</a>
<st:nbsp/>
View
0  .../model/ScannerOffJobProperty/config.jelly → ...bfa/model/ScannerJobProperty/config.jelly
File renamed without changes
View
0  ...ScannerOffJobProperty/help-doNotScan.html → ...el/ScannerJobProperty/help-doNotScan.html
File renamed without changes
View
9 ...ces/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndication/config.jelly
@@ -26,4 +26,13 @@
<f:entry title="${%Pattern}" field="pattern">
<f:textbox/>
</f:entry>
+ <f:advanced>
+ <f:entry title="${%Test text}" field="testText">
+ <f:textbox name="testText"/>
+ </f:entry>
+ <f:validateButton title="${%Match Text}"
+ progress="${%Matching...}"
+ method="matchText"
+ with="pattern,testText"/>
+ </f:advanced>
</j:jelly>
View
1  ...m/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndication/help-testText.html
@@ -0,0 +1 @@
+A text to match against the pattern.
View
41 ...sources/com/sonyericsson/jenkins/plugins/bfa/model/indication/FoundIndication/index.jelly
@@ -1,41 +0,0 @@
-<!--
- ~ The MIT License
- ~
- ~ Copyright 2012 Sony Ericsson Mobile Communications. All rights reserved.
- ~ Copyright 2012 Sony Mobile Communications AB. All rights reserved.
- ~
- ~ 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.
- -->
-<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler">
- <l:layout title="${%Build Log}">
- <l:header>
- <style type="text/css" media="all">
- .errorLine
- {
- background: red;
- color: white;
- }
- </style>
- </l:header>
- <st:include it="${it.build}" page="sidepanel.jelly"/>
- <l:main-panel>
- ${it.getModifiedLog()}
- </l:main-panel>
- </l:layout>
-</j:jelly>
View
151 ...nkins/plugins/bfa/FailureScannerTest.java → ...ns/bfa/BuildFailureScannerHudsonTest.java
@@ -27,13 +27,15 @@
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.ToGerritRunListener;
import com.sonyericsson.jenkins.plugins.bfa.db.KnowledgeBase;
import com.sonyericsson.jenkins.plugins.bfa.db.LocalFileKnowledgeBase;
import com.sonyericsson.jenkins.plugins.bfa.model.FailureCause;
import com.sonyericsson.jenkins.plugins.bfa.model.FailureCauseBuildAction;
import com.sonyericsson.jenkins.plugins.bfa.model.FoundFailureCause;
-import com.sonyericsson.jenkins.plugins.bfa.model.ScannerOffJobProperty;
+import com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.BuildLogIndication;
+import com.sonyericsson.jenkins.plugins.bfa.model.indication.FoundIndication;
import com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication;
import com.sonyericsson.jenkins.plugins.bfa.statistics.FailureCauseStatistics;
import com.sonyericsson.jenkins.plugins.bfa.statistics.Statistics;
@@ -42,6 +44,7 @@
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Result;
+import hudson.model.listeners.RunListener;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.MockBuilder;
import org.mockito.ArgumentMatcher;
@@ -51,15 +54,16 @@
import org.powermock.reflect.Whitebox;
import java.io.IOException;
+import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.verify;
import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
//CS IGNORE MagicNumber FOR NEXT 300 LINES. REASON: TestData.
@@ -70,7 +74,7 @@
* @author Tomas Westling &lt;thomas.westling@sonyericsson.com&gt;
*/
-public class FailureScannerTest extends HudsonTestCase {
+public class BuildFailureScannerHudsonTest extends HudsonTestCase {
private static final String TO_PRINT = "ERROR";
@@ -90,26 +94,87 @@ public void testOneIndicationFound() throws Exception {
FreeStyleBuild build = future.get(10, TimeUnit.SECONDS);
assertBuildStatus(Result.FAILURE, build);
+
FailureCauseBuildAction action = build.getAction(FailureCauseBuildAction.class);
assertNotNull(action);
List<FoundFailureCause> causeListFromAction = action.getFoundFailureCauses();
assertTrue(findCauseInList(causeListFromAction, failureCause));
WebClient web = createWebClient();
- HtmlPage page = web.goTo("/" + build.getUrl() + action.getUrlName() + "/1/1");
+ HtmlPage page = web.goTo("/" + build.getUrl() + "console");
HtmlElement document = page.getDocumentElement();
- HtmlElement focus = document.getElementById("focusLine");
- List<HtmlElement> errorElements = document.getElementsByAttribute("span", "class", "errorLine");
+
+ FoundFailureCause foundFailureCause = causeListFromAction.get(0);
+ FoundIndication foundIndication = foundFailureCause.getIndications().get(0);
+ String id = foundIndication.getMatchingLine() + foundFailureCause.getId();
+ HtmlElement focus = document.getElementById(id);
+ assertNotNull(focus);
+
+ List<HtmlElement> errorElements = document.getElementsByAttribute("span", "title", foundFailureCause.getName());
assertNotNull(errorElements);
HtmlElement error = errorElements.get(0);
+
+ assertNotNull(error);
+ assertEquals("Error message not found: ", TO_PRINT, error.getTextContent().trim());
+ }
+
+ /**
+ * Happy test that should find one failure indication in the build.
+ *
+ * @throws Exception if so.
+ */
+ public void testTwoIndicationsSameLine() throws Exception {
+ FreeStyleProject project = createProject();
+
+ FailureCause failureCause = configureCauseAndIndication();
+
+ Indication indication = new BuildLogIndication(".*ERROR.*");
+ FailureCause failureCause2 = configureCauseAndIndication("Other cause", "Other description", indication);
+
+ Future<FreeStyleBuild> future = project.scheduleBuild2(0, new Cause.UserCause());
+
+ FreeStyleBuild build = future.get(10, TimeUnit.SECONDS);
+ assertBuildStatus(Result.FAILURE, build);
+
+ FailureCauseBuildAction action = build.getAction(FailureCauseBuildAction.class);
+ assertNotNull(action);
+ List<FoundFailureCause> causeListFromAction = action.getFoundFailureCauses();
+ assertTrue(findCauseInList(causeListFromAction, failureCause));
+ assertTrue(findCauseInList(causeListFromAction, failureCause2));
+
+ WebClient web = createWebClient();
+ HtmlPage page = web.goTo("/" + build.getUrl() + "console");
+
+ HtmlElement document = page.getDocumentElement();
+
+ FoundFailureCause foundFailureCause = causeListFromAction.get(0);
+ FoundIndication foundIndication = foundFailureCause.getIndications().get(0);
+ String id = foundIndication.getMatchingLine() + foundFailureCause.getId();
+ HtmlElement focus = document.getElementById(id);
+ assertNotNull(focus);
+
+ foundFailureCause = causeListFromAction.get(0);
+ foundIndication = foundFailureCause.getIndications().get(0);
+ id = foundIndication.getMatchingLine() + foundFailureCause.getId();
+ focus = document.getElementById(id);
assertNotNull(focus);
+
+ String title = failureCause.getName() + "\n" + failureCause2.getName();
+
+ List<HtmlElement> errorElements = document.getElementsByAttribute("span", "title", title);
+ //The titles could be in any given order, trying both orders before failing.
+ if (errorElements.size() < 1) {
+ title = failureCause2.getName() + "\n" + failureCause.getName();
+ errorElements = document.getElementsByAttribute("span", "title", title);
+ }
+ assertTrue("Title not found in annotated text", errorElements.size() > 0);
+ HtmlElement error = errorElements.get(0);
assertNotNull(error);
- assertEquals("Error message not found: ", error.getTextContent(), TO_PRINT);
+ assertEquals("Error message not found: ", TO_PRINT, error.getTextContent().trim());
}
/**
- * One indication should be found and a correct looking Gerrit-Trigger-Plugin
- * message can be constructed.
+ * One indication should be found and a correct looking Gerrit-Trigger-Plugin message can be constructed.
*
* @throws Exception if so.
*/
@@ -128,14 +193,14 @@ public void testOneIndicationBuildCompletedMessage() throws Exception {
GerritMessageProviderExtension messageProvider = new GerritMessageProviderExtension();
assertEquals("The " + GerritMessageProviderExtension.class.getSimpleName()
- + " extension would not return the expected message." ,
+ + " extension would not return the expected message.",
"This is an error",
messageProvider.getBuildCompletedMessage(build));
PluginImpl.getInstance().setGerritTriggerEnabled(false);
assertNull("The " + GerritMessageProviderExtension.class.getSimpleName()
- + " extension would not return null." ,
+ + " extension would not return null.",
messageProvider.getBuildCompletedMessage(build));
}
@@ -193,14 +258,16 @@ public void testDoNotScanGlobal() throws Exception {
}
/**
- * Tests that there is no scanner result when the property {@link ScannerOffJobProperty} is set to true.
+ * Tests that there is no scanner result when the property
+ * {@link com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty}
+ * is set to true.
*
* @throws Exception if so.
*/
public void testDoNotScanSpecific() throws Exception {
PluginImpl.getInstance().setGlobalEnabled(true);
FreeStyleProject project = createProject();
- project.addProperty(new ScannerOffJobProperty(true));
+ project.addProperty(new ScannerJobProperty(true));
configureCauseAndIndication();
Future<FreeStyleBuild> future = project.scheduleBuild2(0, new Cause.UserCause());
FreeStyleBuild build = future.get(10, TimeUnit.SECONDS);
@@ -250,6 +317,31 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
}
/**
+ * Tests that {@link BuildFailureScanner} is found before
+ * {@link com.sonyericsson.hudson.plugins.gerrit.trigger.gerritnotifier.ToGerritRunListener}.
+ */
+ public void testOrdinal() {
+ int counter = 0;
+ int bfaPlacement = 0;
+ int gtPlacement = 0;
+ boolean bfaFound = false;
+ boolean gtFound = false;
+
+ for (RunListener listener : RunListener.all()) {
+ if (listener instanceof BuildFailureScanner) {
+ bfaFound = true;
+ bfaPlacement = (counter++);
+ } else if (listener instanceof ToGerritRunListener) {
+ gtFound = true;
+ gtPlacement = (counter++);
+ }
+ }
+ assertTrue(gtFound);
+ assertTrue(bfaFound);
+ assertTrue("BFA (" + bfaPlacement + ") should list before GT (" + gtPlacement + ")", bfaPlacement < gtPlacement);
+ }
+
+ /**
* ArgumentMatcher for a Statistics object.
*/
public static class IsValidStatisticsObject extends ArgumentMatcher<Statistics> {
@@ -260,9 +352,9 @@ public boolean matches(Object o) {
}
Statistics stat = (Statistics)o;
if (stat.getBuildNumber() != 1) {
- return false;
+ return false;
}
- List<FailureCauseStatistics> failureCauseStatisticsList = stat.getFailureCauseStatisticsList();
+ List<FailureCauseStatistics> failureCauseStatisticsList = stat.getFailureCauseStatisticsList();
if (failureCauseStatisticsList == null || failureCauseStatisticsList.size() != 1) {
return false;
}
@@ -279,11 +371,12 @@ public boolean matches(Object o) {
* Convenience method for a standard cause that finds {@link #TO_PRINT} in the build log.
*
* @return the configured cause that was added to the global config.
+ * @throws Exception if something goes wrong in handling the causes.
*
* @see #configureCauseAndIndication(com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication)
* @see #configureCauseAndIndication(String, String, com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication)
*/
- private FailureCause configureCauseAndIndication() {
+ private FailureCause configureCauseAndIndication() throws Exception {
return configureCauseAndIndication(new BuildLogIndication(".*ERROR.*"));
}
@@ -294,21 +387,25 @@ private FailureCause configureCauseAndIndication() {
*
* @param indication the indication for the cause.
* @return the configured cause that was added to the global config.
+ * @throws Exception if something goes wrong in handling the causes.
*
* @see #configureCauseAndIndication(String, String, com.sonyericsson.jenkins.plugins.bfa.model.indication.Indication)
*/
- private FailureCause configureCauseAndIndication(Indication indication) {
+ private FailureCause configureCauseAndIndication(Indication indication) throws Exception {
return configureCauseAndIndication("Error", "This is an error", indication);
}
/**
* Convenience method for a standard cause with a category and the provided indication.
- * @param name the name of the cause.
+ *
+ * @param name the name of the cause.
* @param description the description of the cause.
- * @param indication the indication.
+ * @param indication the indication.
* @return the configured cause that was added to the global config.
+ * @throws Exception if something goes wrong in handling the causes.
*/
- private FailureCause configureCauseAndIndication(String name, String description, Indication indication) {
+ private FailureCause configureCauseAndIndication(String name, String description, Indication indication)
+ throws Exception {
return configureCauseAndIndication(name, description, "category", indication);
}
@@ -317,16 +414,22 @@ private FailureCause configureCauseAndIndication(String name, String description
*
* @param name the name of the cause.
* @param description the description of the cause.
- * @param category the category of the cause.
+ * @param category the category of the cause.
* @param indication the indication.
* @return the configured cause that was added to the global config.
+ * @throws Exception if something goes wrong in handling the causes.
*/
private FailureCause configureCauseAndIndication(String name, String description, String category,
- Indication indication) {
+ Indication indication) throws Exception {
List<Indication> indicationList = new LinkedList<Indication>();
indicationList.add(indication);
FailureCause failureCause = new FailureCause(name, name, description, category, indicationList);
+
+ Collection<FailureCause> causes = PluginImpl.getInstance().getKnowledgeBase().getCauses();
+
+
List<FailureCause> causeList = new LinkedList<FailureCause>();
+ causeList.addAll(causes);
causeList.add(failureCause);
Whitebox.setInternalState(PluginImpl.getInstance(), KnowledgeBase.class, new LocalFileKnowledgeBase(causeList));
return failureCause;
@@ -356,7 +459,7 @@ private FreeStyleProject createProject() throws IOException {
private boolean findCauseInList(List<FoundFailureCause> causeListFromAction, FailureCause failureCause) {
for (FoundFailureCause cause : causeListFromAction) {
if (failureCause.getName().equals(cause.getName())
- && failureCause.getDescription().equals(cause.getDescription())
+ && failureCause.getDescription().equals(cause.getDescription())
&& failureCause.getCategories().equals(cause.getCategories())) {
return true;
}
View
25 ...st/java/com/sonyericsson/jenkins/plugins/bfa/model/indication/BuildLogIndicationTest.java
@@ -24,10 +24,12 @@
*/
package com.sonyericsson.jenkins.plugins.bfa.model.indication;
+import com.sonyericsson.jenkins.plugins.bfa.Messages;
import com.sonyericsson.jenkins.plugins.bfa.model.BuildLogFailureReader;
import com.sonyericsson.jenkins.plugins.bfa.test.utils.PrintToLogBuilder;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
+import hudson.util.FormValidation;
import org.jvnet.hudson.test.HudsonTestCase;
/**
@@ -64,4 +66,27 @@ public void testBuildLogFailureReaderUnsuccessful() throws Exception {
FoundIndication found = reader.scan(build, System.out);
assertNull(found);
}
+
+ /**
+ * Tests that the doMatchText method behaves correctly when the pattern is valid and the string matches the pattern.
+ */
+ public void testDoMatchTextOk() {
+ BuildLogIndication.BuildLogIndicationDescriptor indicationDescriptor =
+ new BuildLogIndication.BuildLogIndicationDescriptor();
+ FormValidation formValidation = indicationDescriptor.doMatchText(".*", "hello");
+ assertEquals(formValidation.getMessage(), Messages.StringMatchesPattern());
+ assertEquals(formValidation.kind, FormValidation.Kind.OK);
+ }
+
+ /**
+ * Tests that the doMatchText method behaves correctly when the pattern is valid and the string does not
+ * match the pattern.
+ */
+ public void testDoMatchTextWarning() {
+ BuildLogIndication.BuildLogIndicationDescriptor indicationDescriptor =
+ new BuildLogIndication.BuildLogIndicationDescriptor();
+ FormValidation formValidation = indicationDescriptor.doMatchText("hi", "hello");
+ assertEquals(formValidation.getMessage(), Messages.StringDoesNotMatchPattern());
+ assertEquals(formValidation.kind, FormValidation.Kind.WARNING);
+ }
}

No commit comments for this range

Something went wrong with that request. Please try again.