How to make maven enforcer plugin to run in a specified phase? - maven

I would like to ensure the file size of resulting zip file is not larger than 400 MB so I've created this rule:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-file-size</id>
<goals>
<goal>enforce-once</goal>
</goals>
<configuration>
<rules>
<requireFilesSize>
<maxsize>419430400</maxsize> <!-- the final zip should not exceed 400 MB -->
<files>
<file>${project.build.outputDirectory}.zip</file>
</files>
</requireFilesSize>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
However, the mvn enforcer is by default bound to the validate phase and unfortunately the file does not exist by this time. The zip file is generated by ant task that is bound to generate-resources mvn phase.
Question
Is there any way to make the mvn enforcer to run after generate-resources? Or to put it another way, how can I verify a build post-condition instead pre-condition?

omg, adding <phase>verify</phase> worked for me:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-file-size</id>
<phase>verify</phase>
<goals>
<goal>enforce-once</goal>
</goals>
<configuration>
<rules>
<requireFilesSize>
<maxsize>419430400</maxsize> <!-- the final zip should not exceed 400 MB -->
<files>
<file>${project.build.outputDirectory}.zip</file>
</files>
</requireFilesSize>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>

Related

Is there a way in maven to assure that a property is set

I just tracked down a difficult maven issue that was caused by a bad property value.
The property is a path to an alternate JVM that is used a run-time by a test.
I would like to make maven fail early by detecting if the path is valid or not.
What might be a way to accomplish this?
I plan to dig into antrun to see if there is a way to make it run first so that it can check, but that seems like overkill.
Question: How can I do this cleanly and simply?
You can use the Enforcer Maven Plugin and its Require Property rule, where you can enforce the existence of a certain property, optionally with a certain value (a matching regex), and fail the build otherwise.
This rule can enforce that a declared property is set and optionally evaluate it against a regular expression.
A simple snippet would be:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-property</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>basedir</property>
<message>You must set a basedir property!</message>
<regex>.*\d.*</regex>
<regexMessage>The basedir property must contain at least one digit.</regexMessage>
</requireProperty>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
Yes, you can use the maven-enforcer-plugin for this task. This plugin is used to enforce rules during the build and it has a built-in requireFilesExist rule:
This rule checks that the specified list of files exist.
The following configuration will enforce that the file ${project.build.outputDirectory}/foo.txt exists and will fail the build if it does not.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-files-exist</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireFilesExist>
<files>
<file>${project.build.outputDirectory}/foo.txt</file>
</files>
</requireFilesExist>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
Use the Require Files Exist rule of the Maven Enforcer plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-files-exist</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireFilesExist>
<files>
<file>${property.to.check}</file>
</files>
</requireFilesExist>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Maven Jacoco Configuration - Exclude classes/packages from report not working

I have a maven multi-module project and I'm using jacoco-maven for code coverage reports. Some classes should not be reported, as they're Spring configuration and I'm not interested in them.
I have declared the maven-jacoco plugin as follow:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.2.201409121644</version>
<configuration>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
<exclude>some.package.*</exclude>
<exclude>**/*Config.*</exclude>
<exclude>**/*Dev.*</exclude>
<exclude>some/package/SomeClass.java</exclude>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
The problem is that when I execute mvn clean verify jacoco still reports classes that should have been excluded as my xml configuration points out. How can I configure it properly?
Your XML is slightly wrong, you need to add any class exclusions within an excludes parent field, so your above configuration should look like the following as per the Jacoco docs
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<configuration>
<excludes>
<exclude>**/*Config.*</exclude>
<exclude>**/*Dev.*</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>jacoco-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
The values of the exclude fields should be class paths (not package names) of the compiled classes relative to the directory target/classes/ using the standard wildcard syntax
* Match zero or more characters
** Match zero or more directories
? Match a single character
You may also exclude a package and all of its children/subpackages this way:
<exclude>some/package/**/*</exclude>
This will exclude every class in some.package, as well as any children. For example, some.package.child wouldn't be included in the reports either.
I have tested and my report goal reports on a reduced number of classes using the above.
If you are then pushing this report into Sonar, you will then need to tell Sonar to exclude these classes in the display which can be done in the Sonar settings
Settings > General Settings > Exclusions > Code Coverage
Sonar Docs explains it a bit more
Running your command above
mvn clean verify
Will show the classes have been excluded
No exclusions
[INFO] --- jacoco-maven-plugin:0.7.4.201502262128:report (post-test) # ** ---
[INFO] Analyzed bundle '**' with 37 classes
With exclusions
[INFO] --- jacoco-maven-plugin:0.7.4.201502262128:report (post-test) # ** ---
[INFO] Analyzed bundle '**' with 34 classes
Though Andrew already answered question with details , i am giving code how to exclude it in pom
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<configuration>
<excludes>
<exclude>**/*com/test/vaquar/khan/HealthChecker.class</exclude>
</excludes>
</configuration>
<executions>
<!-- prepare agent for measuring integration tests -->
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
For Springboot application
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<excludes>
<!-- Exclude class from test coverage -->
<exclude>**/*com/khan/vaquar/Application.class</exclude>
<!-- Exclude full package from test coverage -->
<exclude>**/*com/khan/vaquar/config/**</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
Another solution:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule implementation="org.jacoco.maven.RuleConfiguration">
<excludes>
<exclude>com.mypackage1</exclude
<exclude>com.mypackage2</exclude>
</excludes>
<element>PACKAGE</element>
<limits>
<limit implementation="org.jacoco.report.check.Limit">
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
<minimum>0.85</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
Please note that, we are using "<element>PACKAGE</element>" in the configuration which then helps us to exclude at package level.
you can configure the coverage exclusion in the sonar properties, outside of the configuration of the jacoco plugin:
...
<properties>
....
<sonar.exclusions>
**/generated/**/*,
**/model/**/*
</sonar.exclusions>
<sonar.test.exclusions>
src/test/**/*
</sonar.test.exclusions>
....
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.coverage.exclusions>
**/generated/**/*,
**/model/**/*
</sonar.coverage.exclusions>
<jacoco.version>0.7.5.201505241946</jacoco.version>
....
</properties>
....
and remember to remove the exclusion settings from the plugin
Some Examples from the SonarQube Docs:
Use sonar.coverage.exclusions property.
mvn clean install -Dsonar.coverage.exclusions=**/*ToBeExcluded.java
This should exclude the classes from coverage calculation.
This Work Like a charm with Spring Boot 2.5.3 and Jacoco 0.8.4 ^_^
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.4</version>
<configuration>
<destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
<dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
<output>file</output>
<append>true</append>
<excludes>
<exclude>**/*com/example/Application.class</exclude>
<exclude>**/*com/example/modal*/**</exclude>
<exclude>**/*com/example/dto*/**</exclude>
<exclude>**/*com/example/mapper*/**</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
https://github.com/jacoco/jacoco/issues/34
These are the different notations for classes we have:
VM Name: java/util/Map$Entry
Java Name: java.util.Map$Entry File
Name: java/util/Map$Entry.class
Agent Parameters, Ant tasks and Maven prepare-agent goal
includes: Java Name (VM Name also works)
excludes: Java Name (VM Name also works)
exclclassloader: Java Name
These specifications allow wildcards * and ?, where * wildcards any number of characters, even multiple nested folders.
Maven report goal
includes: File Name
excludes: File Name
These specs allow Ant Filespec like wildcards *, ** and ?, where * wildcards parts of a single path element only.
Here is the working sample in pom.xml file.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<dataFile>target/jacoco.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>target/jacoco-ut</outputDirectory>
<rules>
<rule implementation="org.jacoco.maven.RuleConfiguration">
<element>PACKAGE</element>
<limits>
<limit implementation="org.jacoco.report.check.Limit">
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
<minimum>0.00</minimum>
</limit>
</limits>
</rule>
</rules>
<excludes>
<exclude>com/pfj/fleet/dao/model/**/*</exclude>
</excludes>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>

Maven dependency plugin - How can I ensure that an artifact is present when using dependency-unpack

I'm wondering if there is a way to enforce the existence of a dependency to unpack when using the dependency-unpack goal of the maven dependency plugin. I'm using the configuration below and the problem is that if there is no dependency specified for "${properties.artifactId}" in the dependencies section of the pom the build goes ahead even though nothing has been unpacked. It invariably fails later at the test stage but it would be so much easier if the build could fail when no dependency is present. So does anyone know of a way that this can be enforced?
Thanks
Piers
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-properties</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeArtifactIds>${properties.artifactId}</includeArtifactIds>
<outputDirectory>${project.build.directory}</outputDirectory>
<includes>${properties.file.name}</includes>
</configuration>
</execution>
</executions>
</plugin>
A couple of executions of the maven-enforcer-plugin should do it. You need one to run before the dependency plugin, to make sure ${properties.artifactId} has a value, then another that runs after the dependency plugin to make sure there are files in the target location. Here's the idea, modify for your requirements.
You may write your own rules too if those available don't quite fit.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>fillInTheVersion</version>
<executions>
<execution>
<id>enforce-config-properties</id>
<phase>validate</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>properties.artifactId</property>
<message><![CDATA[### Missing property 'properties.artifactId': the artifact that ....]]></message>
</requireProperty>
</rules>
</configuration>
</execution>
<execution>
<id>enforce-files-exist</id>
<phase>process-resources</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireFilesExist>
<files>
<file>${project.build.directory}/${properties.artifactId}</file>
</files>
<message><![CDATA[### Did not find unpacked artifact ...]]></message>
</requireFilesExist>
</rules>
</configuration>
</execution>
</executions>
</plugin>

Remove or delete resource files from target directory using pom file

I have two profiles in pom.xml, and I have some resource files which I have added into target resource directory: ${project.build.outputDirectory}/resources during execution of the first profile. What I need to do is remove those resource files during execution of the second profile.
Is there any way to remove or delete existing files from target directory?
I do agree with Matthew's observations, but I got the impression that the original poster was asking how to automate execution of clean during (normal) "execution" of a profile.
You can define a plugin execution for the Maven Clean Plugin. It is normally only bound to clean, but by defining a plugin execution you can bind clean:clean (that is the clean goal of the clean plugin) to whichever lifecycle phase you want. The documentation of the Maven Clean Plugin has an example of how to do this. The documentation also has an example of deleting additional files. Merged the two looks like this:
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>auto-clean</id>
<phase>initialize</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<filesets>
<fileset>
<directory>some/relative/path</directory>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
I got the solution..!!
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete>
<fileset dir="${project.build.outputDirectory}/resources" includes="*.xml" />
</delete>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
for reference - http://maven.apache.org/guides/mini/guide-building-for-different-environments.html
mvn clean will remove the target directory (and therefore all the files in it). If you want to remove only certain files from the target directory, a combination of:
excludeDefaultDirectories to stop it from deleting the whole directory, and
filesets to tell it what to delete
ref: http://maven.apache.org/plugins/maven-clean-plugin/clean-mojo.html
Solution with Apache Maven AntRun Plugin 1.8:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<delete
dir="${project.build.outputDirectory}/resources"
includeemptydirs="true"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
I needed only a couple of files deleted from the output directory, the following worked fine for me.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete file="${project.build.outputDirectory}/appContextLocal.xml" />
<delete
file="${project.build.outputDirectory}/appContextServer.xml" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
I also figured that you can run any ant commands here replace what ever task you need in between the <tasks> .... </tasks> and it will work.
List of ant tasks that you can perform are here
Ref: http://maven.apache.org/plugins/maven-antrun-plugin/usage.html
thanks to above answers. finally i came to something like:
if you want to just delete some directories in target folder, you have to create some construct like this.
this for instance deletes just all contents of folders:
target/unpack
gen-external-apklibs
excludeDefaultDirectories allows to not delete complete target folder.
i used it to clean up target folder before lint analysis.
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>Deleting all unnecessary files before lint analysis</id>
<phase>verify</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>target/unpack</directory>
<followSymlinks>false</followSymlinks>
<excludes>
<exclude>*</exclude>
</excludes>
</fileset>
<fileset>
<directory>gen-external-apklibs</directory>
<followSymlinks>false</followSymlinks>
<excludes>
<exclude>*</exclude>
</excludes>
</fileset>
</filesets>
<verbose>true</verbose>
</configuration>
</plugin>

how to Include the buildnumber in maven pdf:pdf

I am trying to include the build number in the pdf's that get generated with the maven pdf plugin. I have all the documentation of the project I am working on written as a maven site. This way all the documentation is stored with the source code.
Pom.xml
So in the pom.xml I have defined the buildnumber plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
<format>{0,date,yyyy-MM-dd_HH-mm}_{1}</format>
<items>
<item>timestamp</item>
<item>${user.name}</item>
</items>
</configuration>
</plugin>
pdf.xml
And in the pdf.xml
<cover>
<coverTitle>${project.name}</coverTitle>
<coverSubTitle>v. ${project.version}</coverSubTitle>
<coverType>Technical documentation</coverType>
<coverVersion>build: ${project.buildNumber}</coverVersion>
<projectName>${project.name}</projectName>
<projectLogo>images/telfortlogo.jpg</projectLogo>
</cover>
I even put resource filtering to ${basedir}/site but it has no effect. I keep getting the ${buildNumber} instead of the result of the buildnumber plugin.
To get something similar working my buildnumber plugin configuration looked like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>pre-site</phase>
<goals>
<goal>create</goal>
</goals>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
<format>{0,date,yyyy-MM-dd_HH-mm}_{1}</format>
<items>
<item>timestamp</item>
<item>${user.name}</item>
</items>
</configuration>
</execution>
</executions>
</plugin>
And in the pdf.xml:
<cover>
<coverTitle>${project.name}</coverTitle>
<coverSubTitle>v. ${project.version} build ${buildNumber}</coverSubTitle>
<coverType>User Guide</coverType>
<projectName>${project.name}</projectName>
</cover>
I believe that your issue comes from the fact that you are executing the buildnumber create goal during the generate-resources phase. And if you are using mvn pdf:pdf or mvn site, the generate-resources will not get executed.
I my setup I have configured the pdf plugin to run on the site phase:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pdf-plugin</artifactId>
<executions>
<execution>
<id>pdf</id>
<phase>site</phase>
<goals>
<goal>pdf</goal>
</goals>
I can then get the pdf to be generated at the end of the site phase.

Resources