Imagine a Java project built using Maven for which I have:
This seems like a typical scenario. Currently, I'm running:
There are two CI jobs configured, both pointing to the project's VCS branch:
The problem is that job 2 unit tests and builds the artifact-under-test all over again (because the verify phase automatically invokes the package phase). This is undesirable for several reasons (in decreasing importance):
So my question is, how can I configure job 2 to use the artifact created by job 1?
I realise I could just have one CI job that runs "mvn verify", which would create the artifact only once, but I want to have the separate CI jobs described above in order to implement a Farley-style deployment pipeline.
In case it helps anyone, here's the full Maven 2 POM of "project 2" in the accepted answer:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.cake</groupId>
<artifactId>cake-acceptance</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>Cake Shop Acceptance Tests</name>
<description>
Runs the automated acceptance tests for the Cake Shop web application.
</description>
<build>
<plugins>
<!-- Compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- Suppress the normal "test" phase; there's no unit tests -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!-- Cargo (starts and stops the web container) -->
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.0.5</version>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- Don't wait for CTRL-C after starting the container -->
<wait>false</wait>
<container>
<containerId>jetty7x</containerId>
<type>embedded</type>
<timeout>20000</timeout>
</container>
<configuration>
<properties>
<cargo.servlet.port>${http.port}</cargo.servlet.port>
</properties>
<deployables>
<deployable>
<groupId>${project.groupId}</groupId>
<artifactId>${target.artifactId}</artifactId>
<type>war</type>
<properties>
<context>${context.path}</context>
</properties>
</deployable>
</deployables>
</configuration>
</configuration>
</plugin>
<!-- Failsafe (runs the acceptance tests) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
<skipTests>false</skipTests>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Add your tests' dependencies here, e.g. Selenium or Sahi,
with "test" scope -->
<dependency>
<!-- The artifact under test -->
<groupId>${project.groupId}</groupId>
<artifactId>${target.artifactId}</artifactId>
<version>${target.version}</version>
<type>war</type>
</dependency>
</dependencies>
<properties>
<!-- The artifact under test -->
<target.artifactId>cake</target.artifactId>
<target.version>0.1.0-SNAPSHOT</target.version>
<context.path>${target.artifactId}</context.path>
<http.port>8081</http.port>
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
Note that even though this "tests" project doesn't create an artifact, it has to use some kind of packaging (I used "jar" here), otherwise no tests are run in the verify phase.
Validate: This step validates if the project structure is correct. For example – It checks if all the dependencies have been downloaded and are available in the local repository. Compile: It compiles the source code, converts the . java files to .
There are three built-in build lifecycles: default, clean and site. The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while the site lifecycle handles the creation of your project's web site.
When you call mvn deploy , mvn will also execute every lifecycle phase before deploy , in order: validate , compile , test , package , verify , install .
Examples of artifacts produced by Maven for a project include: JARs, source and binary distributions, WARs. Each artifact is identified by a group id, an artifact ID, a version, an extension and a classifier (extension+classifier may be named by a type).
Try two maven projects. The first one contains the build and unit tests. You install the artifacts in your local repository. The second job runs the second maven project which declares the artifacts of the first project as dependencies and runs the functional tests.
Not sure if the scenario I just described is possible, but I think it is.
For a quick improvement you can bypass the unit test with -Dmaven.test.skip=true
. If you pass the revision number of your code in your scm to the second job, you should be able to checkout the same source code.
You can also check into the Clone Workspace SCM plugin. This might offer you some additional options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With