Skip to content

Commit

Permalink
JENKINS-54038 support multiple jacoco reports
Browse files Browse the repository at this point in the history
  • Loading branch information
cyrille-leclerc authored and Cyrille Le Clerc committed May 19, 2019
1 parent bf3adff commit 65fd7c3
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@
import org.w3c.dom.Element;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import javax.annotation.Nonnull;

Expand Down Expand Up @@ -128,12 +132,8 @@ public void process(@Nonnull StepContext context, @Nonnull Element mavenSpyLogsE
if (jacocoPrepareAgentEvents.isEmpty()) {
LOGGER.log(Level.FINE, "No org.jacoco:jacoco-maven-plugin:prepare-agent execution found");
return;
} else if (jacocoPrepareAgentEvents.size() > 1) { // JENKINS-54139
if (LOGGER.isLoggable(Level.FINE))
listener.getLogger().print("[withMaven - Jacoco] More than 1 Maven module (" + jacocoPrepareAgentEvents.size() + ") generated a Jacoco code coverage report, " +
"skip automatic collect of Jacoco reports as the Jenkins Jacoco report is not designed to render multiple reports per build");
return;
}

try {
Class.forName("hudson.plugins.jacoco.JacocoPublisher");
} catch (ClassNotFoundException e) {
Expand All @@ -143,6 +143,7 @@ public void process(@Nonnull StepContext context, @Nonnull Element mavenSpyLogsE
return;
}

List<JacocoReportDetails> jacocoReportDetails = new ArrayList<>();

for (Element jacocoPrepareAgentEvent : jacocoPrepareAgentEvents) {

Expand Down Expand Up @@ -200,24 +201,54 @@ public void process(@Nonnull StepContext context, @Nonnull Element mavenSpyLogsE

listener.getLogger().println("[withMaven] jacocoPublisher - Archive JaCoCo analysis results for Maven artifact " + mavenArtifact.toString() + " generated by " +
pluginInvocation + ": execFile: " + destFile + ", sources: " + sourceDirectoryRelativePath + ", classes: " + classesDirectoryRelativePath);
JacocoPublisher jacocoPublisher = new JacocoPublisher();

jacocoPublisher.setExecPattern(destFile);
jacocoPublisher.setSourcePattern(sourceDirectoryRelativePath);
jacocoPublisher.setClassPattern(classesDirectoryRelativePath);

try {
jacocoPublisher.perform(run, workspace, launcher, listener);
} catch (Exception e) {
listener.error("[withMaven] jacocoPublisher - Silently ignore exception archiving JaCoCo results for Maven artifact " + mavenArtifact.toString() + " generated by " +
pluginInvocation + ": " + e);
LOGGER.log(Level.WARNING, "Exception processing " + XmlUtils.toString(jacocoPrepareAgentEvent), e);
jacocoReportDetails.add(new JacocoReportDetails(destFile, sourceDirectoryRelativePath, classesDirectoryRelativePath, mavenArtifact.toString() + " " + pluginInvocation));
}

JacocoPublisher jacocoPublisher = new JacocoPublisher();

String aggregatedDestFile = jacocoReportDetails.stream().map(details -> details.execFile).collect(Collectors.joining(","));
String aggregatedSourceDirectory = jacocoReportDetails.stream().map(details -> details.sourceDirectory).collect(Collectors.joining(","));
String aggregatedClassesDirectory = jacocoReportDetails.stream().map(details -> details.classesDirectory).collect(Collectors.joining(","));

jacocoPublisher.setExecPattern(aggregatedDestFile);
jacocoPublisher.setSourcePattern(aggregatedSourceDirectory);
jacocoPublisher.setClassPattern(aggregatedClassesDirectory);

try {
jacocoPublisher.perform(run, workspace, launcher, listener);
} catch (Exception e) {
listener.error("[withMaven] jacocoPublisher - Silently ignore exception archiving JaCoCo results for " + jacocoReportDetails);
listener.error("[withMaven] jacocoPublisher - Silently ignore exception archiving JaCoCo results: " + e);

if (LOGGER.isLoggable(Level.FINE)) {
StringWriter buffer = new StringWriter();
PrintWriter printWriter = new PrintWriter(buffer);
e.printStackTrace(printWriter);
listener.error(buffer.toString());
}
}
}

public static class JacocoReportDetails {
final String execFile, sourceDirectory, classesDirectory, description;

public JacocoReportDetails(String execFile, String sourceDirectory, String classesDirectory, String description) {
this.execFile = execFile;
this.sourceDirectory = sourceDirectory;
this.classesDirectory = classesDirectory;
this.description = description;
}

@Override
public String toString() {
return "JacocoReportDetails{" +
"execFile='" + execFile + '\'' +
", sourceDirectory='" + sourceDirectory + '\'' +
", classesDirectory='" + classesDirectory + '\'' +
", description='" + description + '\'' +
'}';
}
}

@Symbol("jacocoPublisher")
@Extension
public static class DescriptorImpl extends AbstractHealthAwarePublisher.DescriptorImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Map;
Expand Down Expand Up @@ -183,7 +184,15 @@ public void maven_build_jar_project_on_master_succeeds() throws Exception {
assertThat(tasksResultAction.getProjectActions().size(), is(1));
}

@Ignore("disable while we can't use ASM 6.x due to jenkins enforcer preventing jars supporting java 11 https://gist.github.com/cyrille-leclerc/ac2ad901c27b3b96fd3efa6ed8062f7c")
/**
*
* <pre>
* ERROR: [withMaven] jacocoPublisher - Silently ignore exception archiving JaCoCo results:
* java.io.IOException: While reading class directory: /var/folders/lq/50t8n2nx7l316pwm8gc_2rt40000gn/T/j h8464991534006021463/jobs/jar-with-jacoco/builds/1/jacoco/classes
* </pre>
* @throws Exception
*/
@Ignore("IOException: While reading class directory: .../jacoco/classes")
@Test
public void maven_build_jar_with_jacoco_succeeds() throws Exception {
loadMavenJarWithJacocoInGitRepo(this.gitRepoRule);
Expand All @@ -205,12 +214,15 @@ public void maven_build_jar_with_jacoco_succeeds() throws Exception {
verifyFileIsFingerPrinted(pipeline, build, "jenkins/mvn/test/jar-with-jacoco/0.1-SNAPSHOT/jar-with-jacoco-0.1-SNAPSHOT.jar");
verifyFileIsFingerPrinted(pipeline, build, "jenkins/mvn/test/jar-with-jacoco/0.1-SNAPSHOT/jar-with-jacoco-0.1-SNAPSHOT.pom");

TestResultAction testResultAction = build.getAction(TestResultAction.class);
assertThat(testResultAction.getTotalCount(), is(2));
List<TestResultAction> testResultActions = build.getActions(TestResultAction.class);
assertThat(testResultActions.size(), is(1));
TestResultAction testResultAction = testResultActions.get(0);
assertThat(testResultAction.getTotalCount(), is(1));
assertThat(testResultAction.getFailCount(), is(0));

// verify Task Scanner is called for jenkins.mvn.test:mono-module-maven-app
JacocoBuildAction jacocoBuildAction = build.getAction(JacocoBuildAction.class);
List<JacocoBuildAction> jacocoBuildActions = build.getActions(JacocoBuildAction.class);
assertThat(jacocoBuildActions.size(), is(1));
JacocoBuildAction jacocoBuildAction = jacocoBuildActions.get(0);
assertThat(jacocoBuildAction.getProjectActions().size(), is(1));
}

Expand Down

0 comments on commit 65fd7c3

Please sign in to comment.