Search code examples
mavenazure-devopsazure-pipelinesjacocojacoco-maven-plugin

Child module CCReport43F6D5EF not found when using azure pipelines task Maven@4


We are migrating to from Maven@3 task to Maven@4 see here. This works fine for most repositories, except for the multi model repository. This give me then the following error:

[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[ERROR] Child module /home/vsts/work/1/s/service/CCReport43F6D5EF of /home/vsts/work/1/s/service/pom.xml does not exist @ 
 @ 
[ERROR] The build could not read 1 project -> [Help 1]
org.apache.maven.project.ProjectBuildingException: Some problems were encountered while processing the POMs:
[ERROR] Child module /home/vsts/work/1/s/service/CCReport43F6D5EF of /home/vsts/work/1/s/service/pom.xml does not exist @ 

    at org.apache.maven.project.DefaultProjectBuilder.build (DefaultProjectBuilder.java:397)
    at org.apache.maven.graph.DefaultGraphBuilder.collectProjects (DefaultGraphBuilder.java:414)
    at org.apache.maven.graph.DefaultGraphBuilder.getProjectsForMavenReactor (DefaultGraphBuilder.java:405)
    at org.apache.maven.graph.DefaultGraphBuilder.build (DefaultGraphBuilder.java:82)
    at org.apache.maven.DefaultMaven.buildGraph (DefaultMaven.java:535)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:220)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:193)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:106)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:963)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:296)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:199)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:77)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:569)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
[ERROR]   
[ERROR]   The project nl.XXX:service:1.0.0-SNAPSHOT (/home/vsts/work/1/s/service/pom.xml) has 1 error
[ERROR]     Child module /home/vsts/work/1/s/service/CCReport43F6D5EF of /home/vsts/work/1/s/service/pom.xml does not exist
[ERROR] 
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException

##[warning]No code coverage found to publish. There might be a build failure resulting in no code coverage or there might be no tests.
##[error]Build failed

My task in azure pipelines looks like this

    - task: Maven@4
      displayName: 'Maven Package'
      inputs:
        mavenPomFile: 'service/pom.xml'
        javaHomeOption: 'JDKVersion'
        jdkVersionOption: '1.17'
        jdkArchitectureOption: 'x64'
        codeCoverageToolOption: jaCoCo
        publishJUnitResults: true
        testResultsFiles: '**/surefire-reports/TEST-*.xml'
        goals: 'clean package'
        isJacocoCoverageReportXML: true
        sonarQubeRunAnalysis: true

The file structure looks like this:

project-root/
│
├── service/
│   ├── pom.xml
│   ├── service-impl/
│   │   └── pom.xml
│   └── service-model/
│       └── pom.xml
│
└── azure-pipelines.yml

Then in the service-impl pom.xml there is a core-libraries/pom.xml which contains the jacoco plugin configuration for all repos. This looks like the following:

            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco-maven-plugin.version}</version>
                <configuration>
                    <excludes>**/*IT, **/CCReport43F6D5EF/</excludes>
                </configuration>
                <executions>
                    <execution>
                        <id>prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <phase>initialize</phase>
                    </execution>
                    <execution>
                        <id>report</id>
                        <goals>
                            <goal>report</goal>
                        </goals>
                        <phase>prepare-package</phase>
                        <configuration>
                            <formats>
                                <format>XML</format>
                            </formats>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-unit-test</id>
                        <goals>
                            <goal>report</goal>
                        </goals>
                        <phase>test</phase>
                    </execution>
                </executions>
            </plugin>

I noticed that when changing from Maven@3 to Maven@4 the command that the pipeline executes is changed slightly.

From

/usr/bin/mvn -f /home/vsts/work/1/s/service/pom.xml clean package -Dsonar.jacoco.reportPaths=/home/vsts/work/1/s/service/CCReport43F6D5EF/jacoco.exec -Dsonar.coverage.jacoco.xmlReportPaths=/home/vsts/work/1/s/service/CCReport43F6D5EF/jacoco.xml org.sonarsource.scanner.maven:sonar-maven-plugin:RELEASE:sonar

To:

/usr/bin/mvn -f /home/vsts/work/1/s/service/pom.xml clean package org.sonarsource.scanner.maven:sonar-maven-plugin:RELEASE:sonar

So it is that the reportPaths and xmlReportPaths are removed which seems to cause the issue. Adding them back to the Maven task with the options attribute in the azure pipeline did not seem to solve the issue. Note that in sonarcloud we get this error message which seems to be related:

Property 'sonar.jacoco.reportPaths' is no longer supported. Use JaCoCo's xml report and sonar-jacoco plugin.

I have searched a lot on the internet and the problem seemed to occur for Maven@3 as well, but for us this kept working. Now since we migrate to Maven@4 it breaks. What I found on it:

  • Here they mention similar problems.
  • I found this documentation for how it should be configured. I did exactly what they mention there. I also found this documentation.
  • Here is some discussion on github about solutions, I tried all of them so far...
  • I noticed that here they mention the plugin does not work with multi projects anymore
  • Notice that in the Maven task definition in the FAQ section they state this

Make sure you have specified #codeCoverageClassFilesDirectories and #codeCoverageSourceDirectories as a task input. These two parameters are optional for a single module project but are required for multi-module projects.

It is unclear to me what is going on and how this should be solved/worked around. I wonder if anyone might have an idea. Thanks in advance


Solution

  • I managed to answer my own questions by actually using this workaround mentioned here.

    1. I changed the JaCoCo coverage to None. It now looks like this:
        - task: Maven@4
          displayName: 'Maven Package with Code Coverage'
          inputs:
            mavenPomFile: 'service/pom.xml'  # Parent POM file
            javaHomeOption: 'JDKVersion'
            jdkVersionOption: '1.17'
            jdkArchitectureOption: 'x64'
            mavenVersionOption: 'Default'
            codeCoverageToolOption: 'None'
            sonarQubeRunAnalysis: true
    
    1. I configured the jacoco plugin in my parent pom like this:
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>${jacoco-maven-plugin.version}</version>
                    <configuration>
                        <excludes>**/*IT</excludes>
                    </configuration>
                    <executions>
                        <execution>
                            <id>prepare-agent</id>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>report</id>
                            <goals>
                                <goal>report</goal>
                            </goals>
                            <phase>test</phase>
                            <configuration>
                                <formats>
                                    <format>XML</format>
                                </formats>
                            </configuration>
                        </execution>
                        <execution>
                            <id>post-unit-test</id>
                            <goals>
                                <goal>report</goal>
                            </goals>
                            <phase>test</phase>
                        </execution>
                    </executions>
                </plugin>
    
    1. I added a aggregrator-pom.xml on the same level as service. This is inspired from the workaround in the github. I changed it according to my needs
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.company.awesome-app.pipeline</groupId>
        <artifactId>code-coverage-merge</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>pom</packaging>
        <name>Awesome App Code Coverage Merge</name>
        <description>Merge Code Coverage from all modules</description>
        <properties>
            <maven.install.skip>true</maven.install.skip>
            <maven.deploy.skip>true</maven.deploy.skip>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <version>1.8</version>
                    <executions>
                        <execution>
                            <phase>generate-resources</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <echo message="Generating JaCoCo Reports" />
                                    <taskdef name="report" classname="org.jacoco.ant.ReportTask">
                                        <classpath path="{basedir}/target/jacoco-jars/org.jacoco.ant.jar" />
                                    </taskdef>
                                    <report>
                                        <executiondata>
                                            <file file="${project.basedir}/service-impl/target/jacoco.exec" />
                                        </executiondata>
                                        <structure name="Jacoco report">
                                            <group name="service-impl">
                                                <classfiles>
                                                    <fileset dir="${project.basedir}/service-impl/target/classes" />
                                                </classfiles>
                                                <sourcefiles encoding="UTF-8">
                                                    <fileset dir="${project.basedir}/service-impl/src/main/java" />
                                                </sourcefiles>
                                            </group>
                                            <group name="service-model">
                                                <classfiles>
                                                    <fileset dir="${project.basedir}/service-model/target/classes" />
                                                </classfiles>
                                            </group>
                                        </structure>
                                        <html destdir="${project.build.directory}/site/jacoco" />
                                        <xml destfile="${project.build.directory}/site/jacoco/jacoco.xml" />
                                        <csv destfile="${project.build.directory}/site/jacoco/jacoco.csv" />
                                    </report>
                                </target>
                            </configuration>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>org.jacoco</groupId>
                            <artifactId>org.jacoco.ant</artifactId>
                            <version>0.8.7</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    </project>
    
    1. In the azure-pipelines.yml I added a task to run the code coverage pom and a task to add it to the pipeline. It now looks like this:
        - task: SonarCloudPublish@2
          inputs:
            pollingTimeoutSec: '300'
    
        - task: Maven@4
          displayName: 'Run code coverage maven'
          inputs:
            mavenPomFile: 'service/aggregator-pom.xml'
            javaHomeOption: 'JDKVersion'
            jdkVersionOption: '1.17'
            jdkArchitectureOption: 'x64'
            mavenVersionOption: 'Default'
    
        - task: PublishCodeCoverageResults@2
          inputs:
            summaryFileLocation: $(System.DefaultWorkingDirectory)/service/target/site/jacoco/jacoco.xml
            pathToSources: $(System.DefaultWorkingDirectory)/service
    

    After doing all of this it works. I only noticed that the UI of the CodeCoverage changed in the new task (I am using @2 instead of @1 compared to the workaround example). The problem is that this lacks some features in the new UI. Some people also mentioned this issue here, but Microsoft does not seem like they are going to fix it. We use the sonarcloud code coverage so so far this does not seem like too much of a problem, except for this hassle.