How to compile all modules but install/deploy only selected modules? - maven

I've a typical multi-module maven project.
There's a Jenkins job which builds and deploys all snapshots to the internal repository.
There's another Jenkins build which checks out code, updates all pom versions, and builds & deploys versioned artifacts.
I would like to optimize the latter by deploying only the needed artifacts: that's 2 or 3 out of 100+ modules.
The build should still compile and test all modules but install/deploy only selected module artifacts to internal repo.
Question: Is there a way to do it?

In this case you could define in your aggregator/parent project (from which the main build should start) to skip the install and deploy executions via a property in order to disable them through all the modules by default. Then, in the few modules where this action should still be performed, you could override the specific property to enable them back again.
Since the whole action is targeting a CI job, I would also suggest to wrap this behavior in a maven profile as following:
In your aggregator/parent project you could define:
<profiles>
<profile>
<id>ci-job</id>
<properties>
<disable.install.deploy>true</disable.install.deploy>
<maven.install.skip>${disable.install.deploy}</maven.install.skip>
<maven.deploy.skip>${disable.install.deploy}</maven.deploy.skip>
</properties>
</profile>
</profiles>
The snippet above is defining withinb the ci-job profile a new property, disable.install.deploy, set to true by default. Its value is then passed to the maven.install.skip propert of the maven-install-plugin:
Set this to true to bypass artifact installation. Use this for artifacts that does not need to be installed in the local repository.
And to the maven.deploy.skip property of the maven-deploy-plugin:
Set this to 'true' to bypass artifact deploy
As such, running the following:
mvn clean install -Pci-job
Would effectively skip install and deploy goals executions across the build (across all modules).
That's half of the job however. In the few modules where you still want this action you could then define the following:
<profiles>
<profile>
<id>ci-job</id>
<properties>
<disable.install.deploy>false</disable.install.deploy>
</properties>
</profile>
</profiles>
That is. Keeping the same profile name it will also be activated via the same global build invocation, setting however the key property to false and as such enabling again install and deploy for the modules where this profile would be added.

Related

Version of parent module in child modules specified in profiles not getting updated by Maven-release-plugin

I have a multimodule project with one module that is slow to build and only used when releasing (release-only). In the an aggregate pom i have all modules specified besides the release-only module. The release-only module is specified in a seperate profile which i activate with the maven-release-plugin and it builds it and release it fine.
The problem is the version of the parent module in the release-only module does not get updated when i run release:prepare, meaning while all other modules build (in both prepare, and perform) with the parent artifact version set correctly, the release-only module still has -SNAPSHOT in the version.
I found this what seems to be related issue. But no sollution.
https://issues.apache.org/jira/browse/MRELEASE-843
Some simplyfied code from the aggregate pom, explaining the structure.
<profile>
<id>build-rpm</id>
<modules>
<module>release-only</module>
</modules>
</profile>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<releaseProfiles>build-rpm</releaseProfiles>
</configuration>
</plugin>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
When running mvn release:prepare i want the versions in all my modules to be updated. (Like the normal mvn versions:set -DnewVersion=xxx which work as expected)
neither mvn release:update-versions
and mvn release:prepare update the versions as expected.
The simple trick is not to exclude the module by a profile instead you should make a profile inside the module. That will prevent you from such issues.
I would suggest to remove the "slow module" from the multi-module build. Instead, create a pipeline in your build server (Jenkins, Bamboo, whatever) that first builds your multi-module project and then (in the case of a release) builds the "slow module".
This way, you avoid all the hassle with modules in profiles and switching modules off and on.

Maven: Define SuperPOM property project.build.directory over command line

I am building my maven project with GitLab CI on a docker file.
I would like to configure my pipeline with a "compile" stage and a "test" stage. To be able to do that, I need to set the property project.build.directory, which is defined in the maven super POM, to the docker cache so the compiled artefact does not get lost between the jobs.
project.build.directory is a predefined maven property. Therefore I would think that I am able define it with the CL parameter -Dproject.build.directory=anotherDir. This somehow does not work and my project still gets built to the default directory target.
If I modify my POM with
<properties>
<buildDir>target</buildDir>
</properties>
<build>
<directory>${buildDir}</directory>
</build>
and call mvn clean install -DbuildDir=customTargetDir, my project gets built to the customTargetDir as expected.
Why is that? I really don't see a difference. I both cases, I define the value of an existing property.

Skip compilation in gmavenplus plugin

I currently work in big project built by Maven which has many integration tests modules which are marked as main (not testing) sources.
I am trying to create a profile which would skip compilation of these modules.
I expected gmaven plugin to allow "skip" configuration parameter but this is not the case.
Is there any way to skip module processing without pointing gmaven plugin to non-existent directory and without copy-paste of all modules except integration tests to a separate profile?
You can put the integration test modules in a separate profile of the parent pom where you list the modules. The profile should be active unless you disable it by setting a property when running the Maven build (-DskipIntegrationTestModules). (Don't use activeByDefault.)
<modules>
<module>my-project</module>
</modules>
<profiles>
<profile>
<id>build-integration-tests</id>
<activation>
<property>
<name>!skipIntegrationTestModules</name>
</property>
</activation>
<modules>
<module>my-project-integration-test</module>
</modules>
</profile>
</profiles>
You can find more details in the Maven Introduction to Build Profiles.
You should also know that it can be dangerous to have modules in build profiles because they could be accidentally left out when doing release builds. I think it should be OK in this case because the profile has to be deactivated explicitly.

How to activate a Maven Profile for a specific module in a mutli-module project

We have a multi-module Maven project consisting of a parent POM and 5 or more modules.
Each module can be deployed to a running server as part of the build if we activate our custom "auto-deploy" profile, which is defined explicitly in each module because how/what gets deployed is a little different for each of the modules.
When building from the parent POM though, if I activate the "auto-deploy" profile, Maven will end up deploying all modules, which is almost never what we need to do (based on our dev process etc). But we do want to build from the root as there can be changes across multiple modules and there are dependencies between some modules.
Is there a way, when building from the parent POM, to activate our custom "auto-deploy" Profile for just one of the Modules, but not all of them?
Thanks
If each of your modules will have it's own "auto-deploy" profile, and profile activation will be triggered by variables passed to mvn command, you will be able to run single mvn command on parent module and decide which modules should be deployed simply by declaring activation variables
<profiles>
<profile>
<id>profileId</id>
<activation>
<property>
<name>profileIdEnabled</name>
<value>true</value>
</property>
</activation>
<properties></properties>
</profile>
</profiles>
and then
mvn -DprofileIdEnabled=true
Check out Maven: The Complete Reference - Section 6.2. Using Advanced Reactor Options.
Starting with the Maven 2.1 release, there are new Maven command line options which allow you to manipulate the way that Maven will build multimodule projects. These new options are:
-rf, --resume-from
Resume reactor from specified project
-pl, --projects
Build specified reactor projects instead of all projects
-am, --also-make
If project list is specified, also build projects required by the list
-amd, --also-make-dependents
If project list is specified, also build projects that depend on projects on the list
To build only module-b from the root directory:
$ mvn --projects module-b install

How can I deploy only the pom file to my snapshot repository in Maven?

I would like to be able to deploy only the POM artifact (file) without the main artifact (JAR, WAR, etc), when running mvn deploy and version is a SNAPSHOT version.
Why?
We several developers working on multiple Maven projects. We have a Hudson server with a job per Maven project and version (e.g. foo-1.2, foo-1.3). Each job builds the project and deploys it to a Nexus server (upon success). Maven projects under development are marked as such by using -SNAPSHOT postfix in the version. For example: 1.2-SNAPSHOT, 1.3-SNAPSHOT.
Here's a sample scenario how a developer work is damaged due to this architecture.
Assume two Maven projects: foo-core and foo-webapp, both at version 1.2-SNAPSHOT.
Developer A is working on foo-core, made several changes and compiled it.
Developer A continues to work, but on foo-webapp.
Developer B started working and changing foo-core. It commits his work and pushes it to the SCM.
Hudson is triggered by SCM; Builds foo-core and deploys it to the snapshot repository in Nexus.
Developer A is running mvn install on foo-webapp. Maven is checking with Nexus, and finds that there is a newer version of foo-core in Nexus. It downloads it (filled with developer B changes) and than it fails compilation, since the changes made by developer A are not in the jar located in the local repository. The download overrides the file installed there by developer A.
Existing Solutions
I looked into maven-deploy-plugin, but this plugin deploys all artifacts attached to the project. If they had a way to configure which artifacts to deploy, it would have been great.
Question: Is there any way to solve this without resorting to writing my own deploy plugin, based on maven-deploy-plugin?
Basically to the -Dfile parameter, instead of the artifact, pass the pom.xml. Run the command and yay! mvn deploy won't give you any issues now. Here's a sample deploy command :
$ mvn deploy:deploy-file -DpomFile=pom.xml -Dfile=./pom.xml -DgroupId=my.group.id -DartifactId=artifact-id -DrepositoryId=bigdata-upload-snapshots -Durl=http://maven.mymaven.com/content/repositories/snapshots/
A prerequisite for this is that the repository be added in your settings.xml
[Edit]: I have supplied the parameters -DgroupId and -DartifactId of the project in the sample deploy command but they're not required (refer to Zac's comment below)
I never heard of such a possibility and also would be very astonished if that would be possible. As the pom and the resulting artifact are some kind of unit it would make no scence (to me) to deploy only parts of them.
Nevertheless you should consider to make a separate pom project which specified dependencies and plugins you might want to use on your JAR/WAR projects like this:
<groupId>foo.bar</groupId>
<artifactId>my-pom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
and then inherit that pom project by your JAR/WAR projects like this:
<parent>
<groupId>foo.bar</groupId>
<artifactId>my-pom</artifactId>
<version>1.0.0</version>
</parent>
This is called project inheritance. You can change and deploy your pom project independent of the "child" artifacts.
EDIT after reading motivation:
As I understand you want to prevent maven to resolve SNAPSHOT artifacts from a repository (so that local version won't be overwritten). Have you ever tried to use the mvn -nsu option (see mvn -help)?
-nsu,--no-snapshot-updates Suppress SNAPSHOT updates
I never tried it but found this reported issue. Nevertheless I would give it a try (as the issue is not commented yet).
This works for me for deploying a pom file only (e.g next to an existing jar):
(Note: you need to specify packaging also, otherwise it will be uploaded as an .xml file which is not what you want.)
mvn deploy:deploy-file \
-Dfile=pom.xml \
-Dpackaging=pom \
-DgroupId=com.mycompany.package \
-DartifactId=my-artifact \
-Dversion=2.0.1 \
-DrepositoryId=serverIdFromSettingsXMLForCredentials \
-Durl=http://repositoryserver/myrepo/
Not exactly the answer these folks were asking for. My situation was I wanted to deploy only the parent pom. I'm using the spring-boot-thin-layout in a child module. This requires the parent module be deployed into artifactory. I added the following into my project. It enables skipping of install and/or deploy phase.
In my parent pom:
<properties>
<disable.install>true</disable.install>
<disable.deploy>true</disable.deploy>
<enable.deployAtEnd>true</enable.deployAtEnd>
</properties>
<profiles>
<profile>
<id>deploy-parent</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<disable.install>true</disable.install>
<disable.deploy>true</disable.deploy>
<deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>
<build>
<finalName>${project.version}</finalName>
</build>
</profile>
</profiles>
And the in my child pom(s) or any module you don't want deployed with parent:
<properties>
<maven.install.skip>${disable.install}</maven.install.skip>
<maven.deploy.skip>${disable.deploy}</maven.deploy.skip>
<deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>
So effectively when I run mvn deploy on the parent pom, it will compile all the modules, not run install on anything, and then at the end deploy any module not having `

Resources