Pass "non D" parameter to jenkins maven build step - maven

I have a couple of "Invoke top-level Maven targets" build steps in a project being build by Jenkins.
In the "Properties" field you can specify an arbitray amount of maven build parameters like
skipTests=true evaluating to -DskipTests=true
However I want to pass a build parameter that must not be preceded by -D and also does not require an equals sign.
Like -Psomething.
Is there any way to do this using the "Invoke top-level Maven targets" or do I need to trigger the mvn build manually via "Execute shell"?
Thanks!

A workaround to passing properties is to set environment variables and read them. See this SO post.
Another workaround is by using a profile. Basically in following example you will have to set environment variable RUNTESTS to true to activate your profile and you can do the intended tasks inside this profile (e.g. running junits conditionally.):
<profile>
<id>runtests</id>
<activation>
<property>
<name>env.RUNTESTS</name>
<value>true</value>
</property>
</activation>
<build>
<finalName>re</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<testFailureIgnore>false</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
</profile>

Related

Run exec-maven-plugin on demand only

Is there a way to configure maven (in general) or the exec-maven-plugin so that it is executed on demand only, but linked up to (and including) test?
I have a test main (java) that I use for ad-hoc testing. I can run it fine from within Eclipse. But I also want to run it from the command line.
However, I do not want it to run with the unit tests (test phase).
But it has to be staged after the test phase, because it uses code from the test subtree and it uses the test classpath.
Here is what I have. It works fine, except that it runs as part of the test phase.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>adhoc-domain-test</id>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.abc.test.AdHocTest</mainClass>
<classpathScope>test</classpathScope>
</configuration>
</plugin>
If I change the phase to (eg) verify, it still gets executed on mvn install.
To run a plugin on demand only, you can wrap the plugin inside a profile that is not active by default, like this:
<profiles>
<profile>
<id>my-profile</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
...
</plugin>
</plugins>
</build>
</profile>
</profiles>
The profiles element goes directly under the project element. You can now run the plugin like this:
mvn -P my-profile ...

Maven - skip plugin if property is empty/null

I want to obtain the following behavior: when I specify a value for the property "my.prop", I want the dependency and clean plugins to be executed. If a value is not specified for that property, I want them to be skipped.
I created "my.prop" like this:
<properties>
<my.prop></my.prop>
</properties>
Then I read that profile activation works only for system properties, so I deleted the above and used the surefire plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<systemPropertyVariables>
<my.prop></my.prop>
</systemPropertyVariables>
</configuration>
</plugin>
I tried using profiles, like this:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<skipDependecyAndCleanPlugins>false</skipDependecyAndCleanPlugins>
</properties>
</profile>
<profile>
<id>skip-dependency-and-clean-plugins</id>
<activation>
<property>
<name>my.prop</name>
<value></value>
<!-- I also tried: <value>null</value> without success.-->
</property>
</activation>
<properties>
<skipDependecyAndCleanPlugins>true</skipDependecyAndCleanPlugins>
</properties>
</profile>
</profiles>
Later, for each plugin I do something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<configuration>
<skip>${skipDependecyAndCleanPlugins}</skip>
</configuration>
....
</plugin>
But the plugins are still executed...
How can I determine Maven to skip the executions of the plugins when "my.prop" is empty/null?
The simplest solution would be to use the activation in the following form:
<profiles>
<profile>
<activation>
<property>
<name>debug</name>
</property>
</activation>
...
</profile>
</profiles>
The above means you can define any value for debug which means -Ddebug is enough.
An empty value can't be defined a pom file cause <value></value> is equivalent to <value/> which means the same as not defined.
Update:
I would suggest to use a profile and NOT a property. So you can simply define on command line mvn -Pxyz install or leave it.
You can use my.prop property in plugin's configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<configuration>
<skip>${my.prop}</skip>
</configuration>
....
</plugin>
Now when you execute:
mvn ... -Dmy.prop=true
then plugin will be skipped
You were very close. You can achieve what you described by using the !my.prop syntax in profile activation.
<build>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<skip>${skipDependecyAndCleanPlugins}</skip>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>skip-dependency-and-clean-plugins</id>
<activation>
<property>
<name>!my.prop</name>
</property>
</activation>
<properties>
<skipDependecyAndCleanPlugins>true</skipDependecyAndCleanPlugins>
</properties>
</profile>
</profiles>
According to Maven documentation, the skip-dependency-and-clean-plugins profile will be activated when the system property my.prop is not defined at all.
Here is a solution that directly addresses the OP's original request: the ability to skip a plugin's execution if a POM property (not a system property) my.prop is not defined. This solution relies on the Apache Maven Help Plugin. It is a kludge, but given Maven's paucity of expression prowess, this is about the best you're gonna get. At least it relies on a well-known, hopefully-maintained plugin, and should work 100% of the time. Oh, and it may make your head explode. Or make you cry. Or both. You've been warned.
First declare the latest version of the Maven Help Plugin in the <build><pluginManagement> section:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.3.0</version>
</plugin>
Then add this "secret sauce" in the <build><plugins> section, which will check to see if my.prop is defined:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>set-is-skip-true-or-prefixed</id>
<phase>validate</phase>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>is-skip</name>
<value>_${my.prop}</value>
<regex>_\$\{my.prop\}</regex>
<replacement>true</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
<execution>
<id>set-is-skip</id>
<phase>initialize</phase>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>is-skip</name>
<value>${is-skip}</value>
<regex>_.*</regex>
<replacement>false</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
</executions>
</plugin>
Now you have a POM property (not a system property) named is-skip, which you can use in any later phase to disable a plugin—provided that plugin has a <skip> or similar option taking a Boolean value. If my.prop is not defined at all, is-skip will be set to true; otherwise is-skip will be set to false.
<plugin>
<groupId>org.example</groupId>
<artifactId>foobar-plugin</artifactId>
<executions>
<execution>
<id>foo</id>
<phase>package</phase>
<goals>
<goal>foo</goal>
</goals>
<configuration>
<skip>${is-skip}</skip>
</configuration>
</execution>
</executions>
</plugin>
There is one caveat: don't define my.prop at all, even to the empty string, or this solution will consider it defined and set is-skip to false. Setting is-skip to true if my.prop is set but empty would require an additional regex evaluation clause above. For my use case I didn't need it, as an empty my.prop isn't valid and I didn't define my.prop at all in the parent POM.
I'll leave it to you to understand how it works (my head exploded already when I was writing it), but I'll be happy to answer any questions.
In step #2 above, be sure and put the two regex evaluations in different phases, such as validate and initialize as used here. The reason is because Maven gets confused if you mix in the same plugins in in the same phase a child POM, and may scramble the execution order. (See MNG-5987.) My kludge of a solution relies on the order of evaluation.

Building multiple Maven profiles for a single Jenkins job

I am trying to build multiple Maven profiles in a single Jenkins job. Each profile changes some code and then creates a jar by executing mvn -Pdev install then mvn -Pprod install in the command line (According to Maven using mvn -Pdev,prod install is supposed to work but it isn't working for me). Here are the two profiles in my project's pom.xml:
<profiles>
<!-- prod profile -->
<profile>
<id>prod</id>
<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.2</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>src/main/java/com/IQzone/android/configuration/AbstractHoldingRefreshable.java</file>
<replacements>
<replacement>
<token>TrUe</token>
<value>TOAST_SWITCH</value>
</replacement>
</replacements>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>prod</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- dev profile -->
<profile>
<id>dev</id>
<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.2</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>src/main/java/com/IQzone/android/configuration/AbstractHoldingRefreshable.java</file>
<replacements>
<replacement>
<token>TOAST_SWITCH</token>
<value>TrUe</value>
</replacement>
</replacements>
</configuration>
</plugin>
<!-- build project with JAVA 1.6 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>dev</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
How would I setup Jenkins to automatically build both of these profiles for a single Jenkins job whenever the job is hit for a build? And put both of these jars in the Artifactory? I have very little Jenkins knowledge and there isn't much information on this on the web.
You could create a Jenkins matrix job. A matrix job allows the same job to run with changing settings (in your case: a string).
Each changing setting is called an axis. In your case you would create a string axis containing the two values: dev and prod.
That way your job would run twice, with both values.
However: your usage of profiles is dangerous. Since the profile used to run the build is not codified into your artifact, your break the "one source revision should always lead to exactly the same target artifact" contract of Maven (see: http://www.blackbuild.com/how-to-really-use-maven-profiles-without-endangering-your-karma/ for a more detailed explanation)
Consider creating either two different artifacts using classifier (-dev and -prod) or even better: create two separate modules of your build, each one creating only one of your target artifacts.
In Maven, if you use mvn -Pdev,prod, then you are activating both profiles simultaneously in one command.
It seems you want 2 distinct run of the command, i.e. something you would achieve on the command line by doing 2 builds:
mvn -Pdev install; mvn -Pprod install
In jenkins you can achieve this with either
one free style project job (with 2 shell builders running the mvn -P$PROFILE install tasks)
2 maven type jobs (that you can chain one after the other using "build after other projects are built").
In addition to Matrix job and multiple maven invocations in a free-style job, there's another way: Run top-level Maven targets as a pre-build step and run the other command via maven jenkins plugin.
Make sure that the pre-build step uses the same maven repo as the other command by supplying -Dmaven.repo.local=/${whatever-it-is}/${EXECUTOR_NUMBER}.
Please refer to other answers for details on matrix job, etc.
You can do it by setting different execution ids to each execution and then trigger the command
mvn -Pdev,prod clean package install

Integration tests with Maven in a Spring project

The question is how can I use different properties files for integration testing. Detailed explanation follows.
I'm trying to do in container integration tests with Maven, using tomcat7-maven-plugin. The project uses Spring and JPA. At present what I've figured out is the following:
Unit test class names follow the pattern *Test and run with mvn test by maven-surefire-plugin
Integration test class names follow the pattern *IT and run with mvn verify by maven-failsafe-plugin
With executions I can trigger to start and stop tomcat and deploy the war file
All of this works and when I run mvn verify Tomcat is started.
However instead of using a regular database, I would like to use an in memory database. My database configuration is defined in the file src/main/resources/META-INF/spring/database.properties loaded through context:property-placeholder.
I tried to define an alternative file in src/test/resources/META-INF/spring/database.properties, but is ignored. I know that is possible to define system properties within tomcat7-maven-plugin, but I don't know how to use them to trigger loading of different properties files.
My tomcat7-maven-plugin configuration is the following:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>9090</port>
<path>/processing</path>
<useTestClasspath>true</useTestClasspath>
<systemProperties>
<example.value.1>alpha</example.value.1>
</systemProperties>
</configuration>
<executions>
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run-war-only</goal>
</goals>
<configuration>
<fork>true</fork>
</configuration>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
</plugin>
Properties are loaded by context-main.xml with the following line:
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
I load context configuration from web.xml with the following:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/context-*.xml</param-value>
</context-param>
Any suggestion on how to load alternative properties file for testing?
One way to do it, is with Maven profiles and the ant plugin. I suspect that is not the most elegant way, and I'm open to listen for better solution, but for now it solves my problem.
A profile is a way to have a different Maven configuration depending on command line arguments, so in my case to run the integration tests, I run the command mvn -Pintegration clean verify. Here integration is the name of the profile, and is defined in pom.xml, after the properties as follows:
<profiles>
<profile>
<id>standard</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Copying test database.properties to ${project.build.outputDirectory}/META-INF/spring/</echo>
<copy file="src/test/resources/META-INF/spring/database.properties"
todir="${project.build.outputDirectory}/META-INF/spring/" verbose="true" overwrite="true" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Using mvn clean package will instead use the standard profile. It's interesting to mention that profiles can also be defined outside the pom, in .m2/settings.xml
See also: Building For Different Environments with Maven 2 -- Notice that the overwrite parameter in the copy is essential or it will work only at random, and is not mentioned in the linked document.

How to "put" maven command line in pom.xml?

How can I "put" a command line parameter to be executed from pom.xml.
For example I have:
mvn clean install -Dmyparameter
And I wish It to be executed from pom.xml instead from command line.
It depends on which phase you need to use the args. It can be done on plugins by changing the configuration parameter.
<pluginManagement>
<plugin>
......
......
<artifactId>maven-release-plugin</artifactId>
<configuration>
<arguments>-Dmaven.test.skip=true -D[other arguments that u need to include]</arguments>
</configuration>
......
......
</plugin> </pluginManagement>
Same way in the sure fire plugin u can skip test and so on!!
You can try to use maven-exec-plugin:
mvn clean install exec:exec -Dexecutable=<absolute path to binary>
Also it can be bound to some phase of lifecycle to be executed in the middle of the build (without explicit call by exec:exec) and defined in profile with activation if property exists to run optionally:
<profiles>
<profile>
<id>exec</id>
<activation>
<property>
<name>executable</name>
</property>
</activation>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>exec</id>
<goals>
<goal>exec</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<executable>${executable}</executable>
</configuration>
</plugin>
</plugins>
</profile>
</profiles>

Resources