Let's say I have a profile "dostuff" defined in a pom.xml that uses a plugin to do some stuff when the user runs mvn -P dostuff:
<profiles>
<profile>
<id>dostuff</id>
<build>
<plugins>
<plugin>
...
</plugin>
<plugins>
</build>
</profile>
<profiles>
The task the profile performs have been replaced by a new non-maven command entirely.
Of course I can just remove the profile, but that has two problems:
It doesn't fail the build, it just produces a warning:
[WARNING] The requested profile "dostuff" could not be activated because
it does not exist.
It doesn't give the user any information that they should use the new command instead.
So, I would like any use of the profile "dostuff" to produce an error with a message telling them to use the new non-maven command instead.
Is that even possible? It's a plus if the solution doesn't require a plugin.
The maven-enforcer-plugin has a built-in rule to require a profile is activated. Perhaps you could write your own rule to ban a profile, using that code as a starting point.
Just put the profile in your pom and use it to show a message and throw an exception. You could e.g. use the Antrun plugin to echo a message.
Related
My project sturcture:
- something-parent
-- something-one
-- something-two
something-parent -> pom.xml:
<packaging>pom</packaging>
<modules>
<module>something-one</module>
<module>something-two</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>io.github.something</groupId>
<artifactId>something-maven-plugin</artifactId>
<version>1.0.0</version>
</plugin>
</plugins>
</build>
Now I want to execute mvn something:help, but I can't: No plugin found for prefix 'something'.
If I remove modules section - it works. It also works in other modules.
It just doesn't work in parent module with modules section. I couldn't find any documentation or literally anything describing this, is this intended? Is there any workaround?
I know io.github.something:something-maven-plugin:1.0.0:help will work, but I need the shortcut version to work.
//Edit1 - I know about settings.xml solution, but it requires manual edit by user, I would like something on a project level
//Edit2 - found out another quirk, it works when I do mvn something:help -N
I understand that you want to use a short name to refer the plugin when calling it from the command line.
To do that, you have to define a plugin group in your settings.xml, as of https://maven.apache.org/settings.html#plugin-groups
In your case it would be:
<pluginGroups>
<pluginGroup>io.github.something</pluginGroup>
</pluginGroups>
This allows you to call:
mvn something:goal
I have inherited a POM that attempts to avoid repeating build steps by using a profile
that is only activated when the step output does not exist:
<profile>
<id>run-once</id>
<activation>
<file>
<missing>target/some-output</missing>
</file>
</activation>
<build>
<plugins>
<plugin>
...
<executions>
<execution>
... slow process to produce target/some-output ...
</execution>
</executions>
</plugin>
</plugins>
</build>
</activation>
However, as maven experts no doubt realized immediately, this does not work if the developer says mvn clean install. Maven calculates the active profiles once, before running clean, and if target/some-output was present, then the run-once profile is not active. The result is that target/some-output is removed by the clean phase but is not recreated in the install phase, and the ensuing WAR is broken because some-output is missing.
Is there a standard solution to this problem (besides avoiding mvn clean install) ? I'm about to make the plugin unconditional to prevent the silent creation of a broken WAR.
More generally, is there a standard technique to prevent mvn from recreating artifacts like some-output that are up-to-date? Or is the idea that if make-style dependency management is important, one should use gradle or rake instead of maven?
I don't think there is a standard solution to this problem. There are though various options that I can think of (there are most likely others as well):
you could obviously activate the profile manually: mvn clean install -Prun-once, but then you have to remember to do that each time of course
configure the maven-enforcer-plugin together with its requireFilesExist rule to make sure the files exist and fail the build if they don't. (at least then you wont get the silent creation of a broken WAR)
modify the profile to have it create the files to a location under your src folder (i.e. src/main/gen) which is excluded from being checked into your source repository (if you are using one), and then configure the maven-resources-plugin and its copy-resources goal to copy these resources to the correct location under your build directory. This way clean wont delete them.
I have a single module project that has some unit tests that require an external hardware device. I don't want these tests to execute unless I indicate that the device is available.
I feel like this is solvable using Maven properties and the SureFire exclusion/inclusion configuration, but I can't quite see how to do it. A similar question shows how to disable/enable all the tests in a project based on a Maven property, but doesn't quite answer my issue.
In summary, I wish to identify a pattern (e.g. **/*ResourceTest.java) that describes the tests I don't want to run, unless I pass a Maven property to enable them.
E.g.
mvn clean install (runs the standard tests, but skips device-related tests)
mvn -Drun.device.tests=true clean install (runs all the tests)
Thanks in advance.
(Edited to remove the misleading usage of the word "resource" > replaced with "hardware device").
You also can just use the JUnit Assume methods to decide (inside the test) if a test should be executed or skipped.
The best option IMHO would however be to 'declare' the device dependend tests to be "integration tests" and let them be executed by the Maven Failsafe Plugin. I think this would be the "build in" maven solution without any profile 'magic'.
The link you provided gave the good answer.
The right way
Use a mix of Profile Management and Surefire Configuration inclusion / exlcusion is the right way.
You should ask yourself WHY you want to activate some tests dependings on a resource. The resource should always been in your classpath.
If not, you probably just want to activate some test manually, for some tricky reasons. In that case consider this is a bad use of Maven (how would you automate that on a distant server for instance ?)
What you asked
If you really really want to do that, because you have some good reasons that we are not aware of, simply use this :
This example will trigger the profile when the generated file target/generated-sources/axistools/wsdl2java/org/apache/maven is missing.
Example from Maven official doc : http://maven.apache.org/guides/introduction/introduction-to-profiles.html
<profiles>
<profile>
<activation>
<file>
<missing>target/generated-sources/axistools/wsdl2java/org/apache/maven</missing>
</file>
</activation>
...
</profile>
</profiles>
As of Maven 2.0.9, the tags and could be interpolated. Supported variables are system properties like ${user.home} and environment variables like ${env.HOME}. Please note that properties and values defined in the POM itself are not available for interpolation here, e.g. the above example activator cannot use ${project.build.directory} but needs to hard-code the path target.
You could find more information here : http://www.sonatype.com/books/mvnref-book/reference/profiles-sect-activation.html
Hope that will help.
Don't hesitate to challenge my point of view with you own reasons (even legacy code ;) ) or experience
To expand on #Jean-Rémy answer, I have done the following in my project POM file:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<excludes>
<exclude>${tests.to.skip}</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<!-- This profile will be used when running tests without a device -->
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<tests.to.skip>**/*DeviceTest.java</tests.to.skip>
</properties>
</profile>
<profile>
<id>device-profile</id>
<activation>
<property>
<name>device</name>
<value>true</value>
</property>
</activation>
<properties>
<!-- Unsure how to match nothing -->
<tests.to.skip>NOTHING</tests.to.skip>
</properties>
</profile>
This creates two profiles, the default profile will exclude the device tests, whereas the "device-profile" will execute all tests.
To execute the device profile, one can execute mvn -Ddevice=true test.
I have a Jenkins build which builds a maven project with -PmyProfile clean package. This works fine. Now I want the project be deployable but in a separate task (JBoss deployment) so it can be triggered explicitly via the jenkins GUI. For that, I have the following in my pom:
<profiles>
<profile>
<id>myProfile</id>
<properties>...</properties>
<build>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.0.0.Final</version>
<configuration>
<hostname>localhost</hostname>
<port>29999</port>
<username>admin</username>
<password>admin</password>
<filename>${project.build.finalName}.war</filename>
<name>my-webapp</name>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Now I only want to call that single deployment via mvn jboss-as:deploy separately. But how would I do that? If I create a second Jenkins project, everything needs to be built again, so that's pretty stupid. Building as a separate module does not work, either (some error with "building single modules not supported for maven 3").
Any ideas?
Thanks
It sucks a little, but you can always get stuff from another Jenkins workspace by using filesystem relative path like ../../SecondJob/workspace (or use symlink). I used to do this for the same case (deploying as separate job) for all my projects and it works, it's just not elegant, but I believe there's no built-in solution in Jenkins for that.
Alternatively, it seems there's Jenkins plugin for that, but I haven't used it and can't tell anything about it.
Possible trick:
Have only one project, but parameterize it with DEPLOY parameter set to FALSE by default. The build will contain your main build as well as an Invoke top-level Maven targets post-build step for deployment. The deployment step will be invoked only if DEPLOY is TRUE. To do that you use Conditional Build Step plugin.
There is a new deploy-only goal added in version 7.5.Final. You can grab the war from the first job with Copy Artifact Plugin.
References:
https://docs.jboss.org/jbossas/7/plugins/maven/latest/deploy-only-mojo.html
https://github.com/jbossas/jboss-as-maven-plugin/pull/56/commits
I have a need to active a profile during release:prepare.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.1</version>
<configuration>
<arguments>-Prelease</arguments>
<preparationGoals>clean validate</preparationGoals>
<goals>test-compile</goals>
</configuration>
</plugin>
</plugin>
</build>
But when I run:
mvn release:prepare -DdryRun=true help:active-profiles
it never show profile release in active list. and it is not show up on active profile list when I do:
mvn release:perform help:active-profiles
I could not not use <releaseProfiles> since I want this profile to be used in both prepare and perform
Thanks!
One thing that I have used in this case is not using the -P argument, but rather triggering the profile through an environment setting using -Denv=release. Then in the POM, I have the profile activation based on the value of env. This has always worked for me. So in the arguments parameter, you could put something like
<arguments>-Denv=release</arguments>
Similar questions can be found here:
Profile activation on both release:prepare and release:perform
maven release plugin ignores releaseProfile
I think there's some misunderstanding here: mvn release:prepare -DdryRun=true help:active-profiles will never show the active profiles used during the release, but it shows the current active profiles. release:prepare will start another Maven thread (separate executable), and only then the release profile is activated.
In the maven-release-plugin-2.4 a lot has been fixed with regards to profiles, especially for Maven3, since some information was not available anymore when using Maven 2 but now is with Maven 3.
See the release notes