1

I'm using the following command

mvn package -DskipTests -q -pl <<my list of projects>> -am exec:exec -Dexec.executable="echo" -Dexec.args='${project.artifact.file}'

to print the list of jar files produced by my build. This is useful on Jenkins where my archive command does not have explicit knowledge about which build it's running.

But I've noticed a problem. If I've defined a test-jar this approach does not detect it. e.g.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.0.2</version>
            <executions>
                <execution>
                    <goals>
                        <goal>test-jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Is there any property that'll allow me to retrieve the name of the test-jar? i.e. Similar to ${project.artifact.file}

Shane Gannon
  • 6,770
  • 7
  • 41
  • 64
  • Because it's an attached artifact. `${project.attachedArtifacts}` will list them, but it won't be very readable. Best solution here would be to use a custom plugin like here http://stackoverflow.com/questions/10454181/how-to-determine-what-artifacts-are-built-from-a-maven-reactor-plan-ie-includi. – Tunaki Feb 20 '17 at 13:26
  • Actual that's perfect. The output is being parsed so this should do. Do you want to put this as the answer? – Shane Gannon Feb 20 '17 at 13:29
  • Why do you need this? What is the purpose of this? – khmarbaise Feb 20 '17 at 14:38
  • In our Jenkins pipeline we've a custom script to archive the output of Maven. It's not my code but I want to see if I can update it to support the test-jar. – Shane Gannon Feb 20 '17 at 14:44

1 Answers1

2

The test JAR isn't output because it isn't a main artifact of the project, but an attached artifact. You can access the attached artifacts with ${project.attachedArtifacts} instead. Note that this will not print the files, but the coordinates of the artifacts, in a [groupId:artifactId:type:classifier:version] format.

It would be possible to make this more generic with a Maven plugin or with an event spy. Another solution that doesn't require all this is to use the GMavenPlus plugin which allows to execute Groovy scripts in the build:

<plugin>
  <groupId>org.codehaus.gmavenplus</groupId>
  <artifactId>gmavenplus-plugin</artifactId>
  <version>1.5</version>
  <executions>
    <execution>
      <goals>
        <goal>execute</goal>
      </goals>
      <phase>install</phase>
      <configuration>
        <scripts>
          <script><![CDATA[
            import org.apache.maven.artifact.Artifact
            log.info(project.artifact.file.path)
            for (Artifact artifact : project.attachedArtifacts) {
              log.info(artifact.file.path)
            }
          ]]></script>
        </scripts>
      </configuration>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>2.4.8</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</plugin>

This has the advantage that you don't need to (ab)use the exec:exec for this, it is completely generic and actually prints the file path (not the coordinates). It will output in the logs the path of the main artifact, and of all the attached artifacts, like this:

[INFO] Using Groovy 2.4.8 to perform execute.
[INFO] ...\test\target\test-0.0.1-SNAPSHOT.jar
[INFO] ...\test\target\test-0.0.1-SNAPSHOT-tests.jar
Community
  • 1
  • 1
Tunaki
  • 132,869
  • 46
  • 340
  • 423
  • Ah... did not notice how attachedArtifacts was printed when I initially tested. Adding an extra plugin is not ideal in my scenario. – Shane Gannon Feb 20 '17 at 14:42
  • @ShaneGannon I think you could have the same Groovy code inside your Jenkins pipeline, after the Maven build. It should work (although I did not test it). There might be a slight configuration so that it can access the `project` (the Maven project instance). – Tunaki Feb 20 '17 at 17:56
  • I'll look into that option. Seems I'd need to add maven to the classpath. – Shane Gannon Feb 21 '17 at 11:20
  • Good suggestion @Tunaki. But I've been unable to create a meaningful MavenProject. I created one with MavenXpp3Reader. But it lacked information such as the artifacts, parent pom, etc. You need to 'run' Maven to get it to populate these properties. I attempted to do this with a ProjectBuildingRequest but it gave an IllegalArgumentException when resolving a org.springframework.boot dependency. The complexity so far makes me think this approach won't work well for me. Both solutions are discussed in http://stackoverflow.com/questions/11525318/how-do-i-obtain-a-fully-resolved-model-of-a-pom-file – Shane Gannon Feb 24 '17 at 15:37
  • @Shane I think you don't need to do that, Jenkins already knows about the MavenProject, [see here](http://stackoverflow.com/a/10009490/1743880), with `def project = currentBuild.getParent().getModules().toArray()[0]`, or perhaps, [see this](http://stackoverflow.com/a/37639425/1743880). – Tunaki Feb 24 '17 at 15:57
  • Any idea why I'd get the following error with this code based on my use of model1 = readMavenPom file: 'pom.xml'? groovy.lang.GroovyRuntimeException: Could not find matching constructor for: org.apache.maven.project.MavenProject(org.apache.maven.model.Model). Really seems like they should match when I create an instance of MavenProject. – Shane Gannon Feb 24 '17 at 18:15
  • @Shane Hmm no, which sounds weird because [there is a constructor taking a `Model`](http://maven.apache.org/ref/3.3.9/maven-core/apidocs/org/apache/maven/project/MavenProject.html#MavenProject(org.apache.maven.model.Model)). Consider asking a separate question directed at Jenkins folks for this. – Tunaki Feb 24 '17 at 18:27