Configuring Findbugs in Jenkins - maven

My goal is to fail jenkins build for my project in case bugs are reported by FindBugs plugin. For that I have integrated FindBugs config in the project's pom.xml & the execution part of the config is below
<executions>
<execution>
<id>analyze-compile</id>
<phase>compile</phase>
<goals><goal>check</goal></goals>
<configuration>
<threshold>High</threshold>
</configuration>
</execution>
</executions>
I found the above config from online sources & with this config, the project is not failing incase of bugs reported by FindBugs. Also I have tried other configs like below
<xmlOutput>true</xmlOutput>
<configuration>
<failOnError>${findbugs.failOnError}</failOnError>
<threshold>High</threshold>
</configuration>
<executions>
<execution>
<id>noFailOnError</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<failOnError>false</failOnError>
</configuration>
</execution>
<execution>
<id>failOnError</id>
<phase>install</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<failOnError>true</failOnError>
</configuration>
</execution>
</executions>
Can someone please let me know what is the correct execution which needs to be used for failing build in case of bugs in FindBugs ?

Below is the correct configuration for find-bugs in pom.xml. It does the following - Perform FindBugs check, Generate xml report during verify phase , Transform it to html & Fail build in case bugs are present during check
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.4.0</version>
<executions>
<execution>
<id>findbug</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
<findbugsXmlOutputDirectory>
${project.build.directory}/findbugs
</findbugsXmlOutputDirectory>
<failOnError>false</failOnError>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>transform</goal>
</goals>
</execution>
</executions>
<configuration>
<transformationSets>
<transformationSet>
<dir>${project.build.directory}/findbugs</dir>
<outputDir>${project.build.directory}/findbugs</outputDir>
<stylesheet>fancy-hist.xsl</stylesheet>
<!--<stylesheet>default.xsl</stylesheet> -->
<!--<stylesheet>plain.xsl</stylesheet> -->
<!--<stylesheet>fancy.xsl</stylesheet> -->
<!--<stylesheet>summary.xsl</stylesheet> -->
<fileMappers>
<fileMapper
implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
<targetExtension>.html</targetExtension>
</fileMapper>
</fileMappers>
</transformationSet>
</transformationSets>
</configuration>
<dependencies>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>findbugs</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.3</version>
<executions>
<execution>
<id>failing-on-high</id>
<phase>install</phase>
<goals>
<goal>findbugs</goal>
<goal>check</goal>
</goals>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
<failOnError>true</failOnError>
</configuration>
</execution>
</executions>
</plugin>

Related

Maven merging changes plugin execution order in same Phase

I'm working on a Project which uses the same Plugin Multiple Times in multiple Parent Pom Files.
Normally, if you use two Plugins in the same maven phase, it will execute the plugin which is first defined in the POM.
In my case Maven merges the Plugins which causes my Plugins to be executed in the wrong order.
I want my Plugins to be executed in the following Order:
first,second,third,fourth
But the order it executes them is:
first,second,fourth,third
These are my POM's:
ParentParentPom.xml
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<configuration></configuration>
<executions>
<execution>
<id>first-plugin-execution</id>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>second-plugin-execution</id>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
ParentPom.xml
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>third-plugin-execution</id>
<phase>compile</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<configuration></configuration>
<executions>
<execution>
<id>fourth-plugin-execution</id>
<phase>compile</phase>
<goals>
<goal>replace
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Effective Pom.xml
I looked into the Effective Pom of my Project and saw that Maven merged the plugins like this:
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<id>first-plugin-execution</id>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
<execution>
<id>fourth-plugin-execution</id>
<phase>compile</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>second-plugin-execution</id>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
<execution>
<id>third-plugin-execution</id>
<phase>compile</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Changing the Phases of the Plugins is not an option because these plugins rely on plugins which are executed in the compile phase and other plugins rely on the execution of the thrith and fourth execution too.
Is there any way I can prevent maven from merging these plugins together, so that they stay in the right order?

Jenkins Jacoco post build action

I have the below dependency in my POM file
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.4.201502262128</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
Below is the structure of my classes
src/main
src/test
I'm trying to run my functional test cases located at src/test and I want to ignore src/main
I've configured as below but it's not running on my test cases
u need to add few other things along with jacoco to get code coverage. because jacoco doesn't get code reports directly.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<sonar.language>java</sonar.language>
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18</version>
<executions>
<execution>
<id>run-unit-tests</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>${skipUnitTests}</skip>
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18</version>
<executions>
<execution>
<id>run-integration-tests</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<skip>${skipIntegrationTests}</skip>
</configuration>
</execution>
</executions>
</plugin>
<profile>
<id>sonar-coverage</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.4.201502262128</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>agent-for-ut</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>agent-for-it</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
and If this doesn't show any code coverage, search if there is file named jacoco.exec in target folder of work-space of your project.

Inegration test using maven

I am trying to create something like integration tests - i am using groovy to send requests and to parse answers. I'd also want starting of jboss and deploying of .ear to be automatically. Using cargo plugin i was able to start jboss. By using exec plugin i am trying to execute perl script that puts ear to deploy folder. Next phase - execute groovy tests, but this phase starts without waiting for ear to be deployed. Is it possible to make phase to wait for server to be deployed to jboss? My pom:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<id>unpack-application-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>${basedir}/src/main/script/appserver/unzip.groovy</source>
<defaults>
<installDirectory>${appserver.install.directory}</installDirectory>
<zipUrl>${appserver.zip.url}</zipUrl>
</defaults>
</configuration>
</execution>
<execution>
<id>prepare-application-server-configs</id>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>${basedir}/src/main/script/appserver/${suffix}/postUnzipAction.groovy</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
</executions>
<configuration>
<wait>false</wait>
<container>
<containerId>${appserver.id}</containerId>
<home>${appserver.home}</home>
<timeout>6000000</timeout> <!--in ms-->
</container>
<configuration>
<properties>
<cargo.servlet.port>${servlet.port}</cargo.servlet.port>
<cargo.rmi.port>${rmi.port}</cargo.rmi.port>
<!-- corresponds to -Djboss.bind.address=0.0.0.0 under jboss -->
<cargo.hostname>0.0.0.0</cargo.hostname>
</properties>
</configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>deploy-with-script</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>perl</executable>
<workingDirectory>.</workingDirectory>
<commandlineArgs>${deploy.pl.cmd} -x redeploy</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
setup and tear down your server before and after integration test phase, something like that:
<executions>
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
Rename your unit tests to be skipped by surefire but executed by maven-failsave-plugin to *IT.java: http://maven.apache.org/surefire/maven-failsafe-plugin/examples/inclusion-exclusion.html

Using Maven to build c++ in eclipse

My Project consists of multiple Java-Projects, one Java-JNI-C++ Project as a Bridge and one pure C++ Project keeping an algorithm library. I managed to write Maven build configurations for all 3 project kinds. So when I'm calling them on the commandline (Windows 7, 64bit) everything works great.
I do not use any make files or something like this. I use exec-maven-plugin to call my mingw 64bit installation without cygwin (and I also didn't at least knowingly install msys). So 2 pure commandline g++ commands each for the JNA and Library Project.
What I need now for a smooth development workflow is to be able to build and debug the this projects from within Eclipse but using the maven build scripts, since I don't want to put work into my poms and additionally configure the eclipse builder. This should be consistent! Furthermore should the error parsing in Eclipse be konsistent with the output of the maven build.
For my Java projects this works greatly out of the box. Eclipse picks up the maven config and CLEAN and BUILD produces exactly what it should. (Though I see that the Java Builder is still active in the project's properties. Why??). But I cannot get it to work with the CDT.
When I disable the C++ Builder Eclipse just builds with maven (what I want), but the clean commands do not work correctly. Also I get errors marked which are not errors by the compiler. Of course this should be consistent.
Are there tutorials for this use case?
I did not find information on that subject. I'm not sure if I'm generally going into a wrong direction missing best practices or something?!
Since this is my first s.o. question, please feel free to give me also feedback on my question. What I can provide I will ;-)
Some Information:
System Windows 7, 64bit
Eclipse Juno, m2e
Library POM:
<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>test</groupId>
<artifactId>mylib</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyLib</name>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<versionRange>[1.1.1,)</versionRange>
<goals>
<goal>exec</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnIncremental>true</runOnIncremental>
</execute>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<id>compile-Windows_x64</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>g++</executable>
<workingDirectory>target/cpp/Windows_x64</workingDirectory>
<arguments>
<argument>-Wall</argument>
<argument>-m64</argument>
<argument>-c</argument>
<argument>-DAPI_EXPORT</argument>
<argument>-g3</argument>
<argument>-std=c++0x</argument>
<argument>../../../src/main/cpp/*.cpp</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>link-Windows_x64</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>g++</executable>
<workingDirectory>target</workingDirectory>
<arguments>
<argument>-shared</argument>
<argument>-s</argument>
<argument>-m64</argument>
<argument>-oMyLib_Windows_x64.dll</argument>
<argument>cpp/Windows_x64/*.o</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
</executions>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>default-test</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-resources</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testResources</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-install</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.0</version>
<executions>
<execution>
<id>default-site</id>
<phase>none</phase>
</execution>
<execution>
<id>default-deploy</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
JNI POM:
<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>test</groupId>
<artifactId>myprog</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyProg</name>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>truezip-maven-plugin</artifactId>
<versionRange>[1.1,)</versionRange>
<goals>
<goal>copy</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnIncremental>true</runOnIncremental>
</execute>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<versionRange>[1.1.1,)</versionRange>
<goals>
<goal>exec</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnIncremental>true</runOnIncremental>
</execute>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>truezip-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>get-library-headers</id>
<goals>
<goal>copy</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<fileset>
<directory>../MyLib/target/mylib-0.0.1-SNAPSHOT-dll.zip</directory>
<includes>
<include>headers/*</include>
</includes>
<outputDirectory>${project.build.directory}/myLib</outputDirectory>
</fileset>
</configuration>
</execution>
<execution>
<id>get-library</id>
<goals>
<goal>copy</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<fileset>
<directory>../MyLib/target/mylib-0.0.1-SNAPSHOT-dll.zip</directory>
<includes>
<include>*.dll</include>
</includes>
<outputDirectory>${project.build.directory}</outputDirectory>
</fileset>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<id>compile-Windows_x64</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>g++</executable>
<workingDirectory>target/cpp/Windows_x64</workingDirectory>
<arguments>
<argument>-Wall</argument>
<argument>-m64</argument>
<argument>-c</argument>
<argument>-g3</argument>
<argument>-std=c++0x</argument>
<argument>-I../../myLib/headers</argument>
<argument>../../../src/main/cpp/*.cpp</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>link-Windows_x64</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>g++</executable>
<workingDirectory>target</workingDirectory>
<arguments>
<argument>-m64</argument>
<argument>-s</argument>
<argument>-oMyProg_Windows_x64.exe</argument>
<argument>cpp/Windows_x64/*.o</argument>
<argument>MyLib_Windows_x64.dll</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
</executions>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>default-test</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-resources</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testResources</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Thankx
Eclipse does not use the Maven build. Instead it configures the JDT according to your POM. This is done through an M2E (Maven to Eclipse) connector. If you want the same to work for CDT, then you would need an M2E connector for that. I'm not aware of an existing one, so you would have to write an Eclipse plugin for that. See http://wiki.eclipse.org/M2E/Extension_Development for details on how to do that.
Of course, you could also use "execute" instead of "ignore" in your lifecycleMapping in the pom. But that would probably make for a pretty slow build, because the whole build would be triggered on each change. And still this wouldn't "magically" make the errors from Maven appear in your files.

Install Maven itself from Maven Central

I have a maven plugin I would like to test against different Maven versions (Ex.: 2.2.1 & 3.0.4). Ideally I don't want users running the build to have to install these exact versions manually.
Is it possible to install specific versions of Maven itself from Maven Central or some other source that would then cache them in the local Maven repo for subsequent builds?
Maven distributions are stored in Maven Central Repository, as you can see here:
http://mvnrepository.com/artifact/org.apache.maven/apache-maven
https://repository.sonatype.org/index.html#nexus-search;gav~org.apache.maven~apache-maven~~~~kw,versionexpand
Therefore, it can be used as a normal dependency with following coordinates:
tar.gz variant:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>apache-maven</artifactId>
<version>3.0.4</version>
<classifier>bin</classifier>
<type>tar.gz</type>
</dependency>
zip variant:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>apache-maven</artifactId>
<version>3.0.4</version>
<classifier>bin</classifier>
<type>zip</type>
</dependency>
The rest is quite standard - you will probably use it in integration test poms, and call them with maven-invoker-plugin as recommended by #khmarbaise.
Why don't you simply just install a Continuous Integration (CI) server such as Jenkins / Hudson / TeamCity / etc? CI servers allow you to run your build against different versions of an SDK.
If your plugin is OSS (and on GitHub), I believe you can get free Jenkins hosting from Cloudbees.
Downloading Maven itself from Maven Central is not possible. You can only download it from their site.
You could do a thing like the following:
<profile>
<id>run-its</id>
<build>
<!-- Download the different Maven versions -->
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0-beta-3</version>
<executions>
<execution>
<id>download-maven-2.0.11</id>
<phase>prepare-package</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>http://archive.apache.org/dist/maven/binaries/</url>
<fromFile>apache-maven-2.0.11-bin.tar.gz</fromFile>
<toDir>${project.build.directory}/maven/download/</toDir>
</configuration>
</execution>
<execution>
<id>download-maven-2.2.1</id>
<phase>prepare-package</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>http://archive.apache.org/dist/maven/binaries/</url>
<fromFile>apache-maven-2.2.1-bin.tar.gz</fromFile>
<toDir>${project.build.directory}/maven/download/</toDir>
</configuration>
</execution>
<execution>
<id>download-maven-3.0.3</id>
<phase>prepare-package</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>http://archive.apache.org/dist/maven/binaries/</url>
<fromFile>apache-maven-3.0.3-bin.tar.gz</fromFile>
<toDir>${project.build.directory}/maven/download/</toDir>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>truezip-maven-plugin</artifactId>
<version>1.0-beta-4</version>
<executions>
<execution>
<id>extract-maven-2.0.11</id>
<goals>
<goal>copy</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<fileset>
<directory>${project.build.directory}/maven/download/apache-maven-2.0.11-bin.tar.gz</directory>
<outputDirectory>${project.build.directory}/maven/tools/</outputDirectory>
</fileset>
</configuration>
</execution>
<execution>
<id>extract-maven-2.2.1</id>
<goals>
<goal>copy</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<fileset>
<directory>${project.build.directory}/maven/download/apache-maven-2.2.1-bin.tar.gz</directory>
<outputDirectory>${project.build.directory}/maven/tools/</outputDirectory>
</fileset>
</configuration>
</execution>
<execution>
<id>extract-maven-3.0.3</id>
<goals>
<goal>copy</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<fileset>
<directory>${project.build.directory}/maven/download/apache-maven-3.0.3-bin.tar.gz</directory>
<outputDirectory>${project.build.directory}/maven/tools/</outputDirectory>
</fileset>
</configuration>
</execution>
</executions>
</plugin>
<!--
This is currently needed due to a bug of the truezip-plugin cause it unpacks without permission!
see http://jira.codehaus.org/browse/MOJO-1796
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>chmod-files</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<chmod file="${project.build.directory}/maven/tools/apache-maven-2.0.11/bin/mvn" perm="+x"/>
<chmod file="${project.build.directory}/maven/tools/apache-maven-2.2.1/bin/mvn" perm="+x"/>
<chmod file="${project.build.directory}/maven/tools/apache-maven-3.0.3/bin/mvn" perm="+x"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<version>1.5</version>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>1.8.4</version>
</dependency>
</dependencies>
<configuration>
<debug>false</debug>
<!-- src/it-ip as for integration tests invoker plugin for the time of transition to maven-invoker-plugin -->
<projectsDirectory>src/it</projectsDirectory>
<showVersion>true</showVersion>
<pomIncludes>
<pomInclude>*/pom.xml</pomInclude>
</pomIncludes>
<preBuildHookScript>setup</preBuildHookScript>
<postBuildHookScript>verify</postBuildHookScript>
<settingsFile>src/it/settings.xml</settingsFile>
</configuration>
<executions>
<execution>
<id>integration-test-maven-2.0.11</id>
<goals>
<goal>install</goal>
<goal>run</goal>
</goals>
<configuration>
<reportsDirectory>${project.build.directory}/invoker-reports-2.0.11</reportsDirectory>
<localRepositoryPath>${project.build.directory}/local-repo-2.0.11</localRepositoryPath>
<cloneProjectsTo>${project.build.directory}/it-2.0.11</cloneProjectsTo>
<mavenHome>${project.build.directory}/maven/tools/apache-maven-2.0.11</mavenHome>
<goals>
<goal>clean</goal>
<goal>test</goal>
</goals>
</configuration>
</execution>
<execution>
<id>integration-test-maven-2.2.1</id>
<goals>
<goal>install</goal>
<goal>run</goal>
</goals>
<configuration>
<reportsDirectory>${project.build.directory}/invoker-reports-2.2.1</reportsDirectory>
<localRepositoryPath>${project.build.directory}/local-repo-2.2.1</localRepositoryPath>
<cloneProjectsTo>${project.build.directory}/it-2.2.1</cloneProjectsTo>
<mavenHome>${project.build.directory}/maven/tools/apache-maven-2.2.1</mavenHome>
<goals>
<goal>clean</goal>
<goal>test</goal>
</goals>
</configuration>
</execution>
<execution>
<id>integration-test-maven-3.0.3</id>
<goals>
<goal>install</goal>
<goal>run</goal>
</goals>
<configuration>
<reportsDirectory>${project.build.directory}/invoker-reports-3.0.3</reportsDirectory>
<localRepositoryPath>${project.build.directory}/local-repo-3.0.3</localRepositoryPath>
<cloneProjectsTo>${project.build.directory}/it-3.0.3</cloneProjectsTo>
<mavenHome>${project.build.directory}/maven/tools/apache-maven-3.0.3</mavenHome>
<goals>
<goal>clean</goal>
<goal>test</goal>
</goals>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
This will download the different Maven version unpack the .tar.gz archives and make mvn executable and use maven-invoker-plugin to run all integration test with these different maven versions.
BUT i can't recommend that. The better way is to use a CI solution (as already mentioned) which contains the different installations of Maven. Than you can run the integration tests for each Maven version separately.

Resources