How to make a maven build fail if source code contains a keyword / regex - maven

Question
How to make a maven build fail if source code contains a keyword / regex?
Bonus
Be able to specify which path to check
Be able to specify which "kind" of path to check :
"I want to be sure that KEYWORD is not contained in 'main' resources. I don't care about 'test'"
"I want to be sure that KEYWORD is not contained in 'test' resources. I don't care about 'main'"
...
Be able to specify on which phase to execute the test (Eg. before compilation)
Solution
(Based on current answers 2013-09-26)
Best solution yet seems to be #BaptisteMathus answer that fully integrates with maven and is platform independant.
In my use case, #GregWhitaker answer is the good one because it's cheaper to implement as I don't care about platform independency (<= the required command is availiable on all my hosts).
The code sample below is a solution based on this answer, it forbids usage of "FIXME" or "Auto-generated method stub" but is assuming that egrep is availiable.
Please see also #MarkOConnor answer that is cleaner in "SONAR enabled" project
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>process-sources</phase>
<configuration>
<executable>egrep</executable>
<successCodes>
<successCode>1</successCode>
</successCodes>
<arguments>
<argument>-rqm</argument>
<argument>1</argument>
<!-- Forbidden Keywords -->
<argument>FIXME|Auto-generated method stub</argument>
<!-- search path -->
<argument>src/main</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Going to SonarQube to do that is not a bad idea.
Anyway, if someone wants to use a maven-only solution, then the right way would then be by using a plugin dedicated to "enforce" things with maven builds. Using exec-maven-plugin is not that standard and certainly too much platform-dependent.
This plugin is logically named maven-enforcer-plugin and writing a custom enforcer rule is actually very simple.

I would create a small program to run these checks and then execute it via the exec-maven-plugin. If you find the keyword in the main resources then just return a non-zero return code which will cause the plugin to fail the build.

Sonar has a taglist plugin, which allows you to search for strings in your comment blocks and specify the severity handling. I'm assuming that is what you're looking for... Parsing the source code itself might require a custom rule for a tool like checkstyle, I haven't tried this approach but it's documented on the Sonar site.
This can be coupled with the build breaker plugin, which fails your build when an alert criteria is breached in your project's quality profile.

I think the taglist-maven-plugin is exactly what you want.

Related

Setup baseline for Maven Findbugs

I have this issue that I have been trying to solve for the better part of a day, but can't really seem to do.
I have set up my maven so that it fails if findbugs finds any bugs. However, because of reasons, I would like to ignore all the bugs that currently exist in the project, and only fail if new bugs are found. A baseline.
I am able to generate an XML file containing a <BugCollection>
with all my current bugs, using FindBugs plugin for IntelliJ. However, supplying this to the maven plugin does nothing.
It seems the maven plugin requires a filter file in this format:
<Match>
<Class name="com.foobar.MyClass" />
</Match>
My question is then: How do I generate this filter file?
It seems that the findbugs:gui is not a great option, as it only allows me to filter on bug type and class. Meaning new bugs of the same type in the same class but a different method would be ignored.
Alternatively: How do I make findbugs for maven ignore existing bugs and only fail on new ones?
Thank you :)
You should use the excludeBugsFile configuration, something like below. The findbugs-baseline.xml is the file exported with the FindBugs-IDEA plugin in Intellij
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<excludeBugsFile>${project.basedir}/findbugs-baseline.xml</excludeBugsFile>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>

GWT-Maven only compile gwt.rpc

I have a situation where I am debugging via -noserver and it forces me to recompile my gwt application everytime one of my RPC objects changes or I get a serialization error (This is well described in the GWT documentation and I understand why it is happening).
That being said, our project is getting quite big and the compile takes a while to complete, which is slowing down our development process. I have optimzed this as much as I can (Using -draftCompile, only doing a single permutation, and skipping all tests) but it's still pretty slow and I have a pretty beastly computer.
This led me to wonder if a better option here would be to get the compiler to only output the necessary files to make serialization work correctly.
Anyone know if this is possible?
Thanks!
You can do it using maven goals.
In Eclipse "run configurations" I have a specific configuration for that.
Goals: gwt:generateAsync gwt:i18n gwt:css
Profiles: dev-ff
The gwt:generateAsync goal is for generating your RPC. This is a standard goal with gwt-maven-plugin (assuming you are using it, of course).
Profiles: dev-ff ensures I'll only generate the code for Firefox.
Here is a part of the maven plugin config. Notice the goals definitions. You'll at least need the servicePattern attribute to tell the plugin where are your RPC interfaces.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>${gwt-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test</goal>
<goal>i18n</goal>
<goal>css</goal>
<goal>generateAsync</goal>
</goals>
</execution>
</executions>
<!-- Plugin configuration. There are many available options, see gwt-maven-plugin
documentation at codehaus.org -->
<configuration>
<servicePattern>**/*RPC.java</servicePattern>
</configuration>
</plugin>
After doing this kind of operation, I often had to open my generated async files to get them in sync with Eclipse. Afterwards we found out we could just delete the gwt-unitCache/ folder in the target/ folder to force the application to use the new RPC classes.
More information about the plugin is available here.

Maven: Bind plugin execution to the execution of another plugin, not to a lifecycle phase

Note regarding the accepted answer: I accepted the answer because of strong circumstantial evidence. Nonetheless, this is circumstantial evidence, so take it with a grain of salt.
How can I have a plugin be triggered when the user runs a plugin goal, not a lifecycle phase? (This has been asked before, but the answer was to use a lifecycle phase.)
Case in point: I need release:branch to invoke regex-plugin to generate a branch with the current version as its name, minus the -SNAPSHOT suffix. This is what I have, which requires the developer to activate a profile and invoke the verify phase. I need the developer to simply invoke release:branch, which in turn should cause regex-plugin to run. In a bit of a marriage to Gitflow.
<profile>
<id>Release Branch</id>
<build>
<plugins>
<!-- On validate, compute the current version without -SNAPSHOT. -->
<!-- Put the result in a property. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<value>${project.version}</value>
<regex>^(.*)-SNAPSHOT$</regex>
<replacement>$1</replacement>
<name>project.unqualifiedVersion</name>
</configuration>
</execution>
</executions>
</plugin>
<!-- Also on validate, run the branch plugin, and use -->
<!-- the non-SNAPSHOT version thus computed in the branch name. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>branch</goal>
</goals>
<configuration>
<branchName>release/${project.unqualifiedVersion}</branchName>
<updateWorkingCopyVersions>true</updateWorkingCopyVersions>
<updateBranchVersions>false</updateBranchVersions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
The intent is for release:branch to move the current snapshot version (say, 1.0.5-SNAPSHOT) into a new branch, which should be named after the version but without the superfluous -SNAPSHOT suffix (1.0.5). The current branch should then take on a new snapshot version (1.1.0-SNAPSHOT, not 1.0.6-SNAPSHOT, because we want release 1.0.x to have room for hotfixes, so we reserve it for the branch) (I don't have the automatic computation of the next snapshot version figured out yet, so, if you run the Maven configuration above with validate, you will have to enter it at a prompt).
The evidence presented so far is rather circumstantial. I've done some research of my own, so it's best I share it here. The below are either more of the same "it's not possible", or the building blocks for alternatives.
jetspeed:mvn plugin --- run a specified sequence of plugins; the configuration to run can be varied via a system property; IDE integration concerns
Executing goals before plugin runs (StackOverflow) --- same question answered in the context of a custom Mojo
Make Mojo run other goals (StackOverflow) --- again, from the context of a custom Mojo
Configuring default Mojo executions --- Maven page describing how Mojos run - more circumstantial evidence
Triggering phases before goal execution (StackOverflow) --- roundabout solution to my problem, unfortunately answered in the negative
INTERESTING: Guide to Ant plugin development --- appealing to me, because, while it requires writing a custom plugin, it's all Ant + Maven configuration, no code to compile; presumably a lower barrier to entry
Creating a parallel lifecycle --- appealing approach, because I could fully control the contents of the lifecycle to where it would use Gitflow verbs; unclear how IDEs would integrate this; learning curve and adoption barrier concerns exist
No, you can't bind to a plugin to another plugin. Only to a phase.
In Maven-internal terms, a "Mojo" is the thing that does work. A "plugin" is a collection of mojos wrapped up so you can reference them from the POM. Mojos bind to phases only.
From the plugin development documentation:
Each Mojo specified inside a plugin descriptor must provide the following
...
phase ... Defines a default phase to bind a mojo execution to if the user does not explicitly set a phase in the POM. Note: This annotation will not automagically make a mojo run when the plugin declaration is added to the POM. It merely enables the user to omit the <phase> element from the surrounding <execution> element.
For further confirmation, see the source of MojoExecution (the JavaDoc for this class isn't helpful) and notice that there are two possible sources of execution enumerated:
An execution that originates from the direct invocation of a goal from the CLI
and
An execution that originates from a goal bound to a lifecycle phase
No other way to kick off an execution means you're out of luck (barring extraordinary measures like rolling your own plugin that combines the effects of the two plugins you want to link and then using your custom plugin).

Configure maven-license-plugin to use excludedGroups correctly

When this plugin is attached to the test or package phase, it causes a multi module build to break since it forces dependency resolution before the module dependencies are in the local repository (first build upon updating to a new snapshot version). I'm trying to get the plugin to ignore the offending com.cons3rt group dependencies which are not required for license output. Tried several variations of:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>aggregate-add-third-party</id>
<configuration>
<excludedGroups>com.cons3rt</excludedGroups>
</configuration>
<phase>package</phase>
<goals>
<goal>aggregate-add-third-party</goal>
</goals>
</execution>
</executions>
Nothing seems to work - looking at the output of mvn -X, it seems like the plugin is not honoring the configuration setting for excludedGroups. Anyone have any luck using this configuration approach?
In your configuration use a pipe to separate multiple groupIds and set the .* to refer to all sub packages:
<excludedGroups>com.group1.*|com.group2.*</excludedGroups>
A workaround for this problem is to pass the parameter through the command line using the
-Dlicense.excludedGroups
parameter.
e.g. mvn package -Dlicense.excludedGroups=com.jhla.*
Simply Change
<excludedGroups>com.cons3rt</excludedGroups>
to
<excludedGroups>^com\.cons3rt</excludedGroups>
as the given string needs to be a regular expression.
For further information, see documentation at:
http://www.mojohaus.org/license-maven-plugin/aggregate-add-third-party-mojo.html

How to rename goals in Maven?

In the Maven document Introduction to the Build Lifecycle, a goal of display:time is described that outputs the current time. The plugin is as follows:
...
<plugin>
<groupId>com.mycompany.example</groupId>
<artifactId>maven-touch-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>timestamp</goal>
</goals>
</execution>
</executions>
</plugin>
...
I have several questions relating to this plugin:
How can I change the name of the goal to, for example, foo:bar? (Why does neither display nor time appear anywhere in the XML fragment? How can you tell, from looking at the fragment, what goals it defines?)
How can I manually run this goal? (For similar constructs, the equivalent of mvn display:time sometimes works, but this doesn't work consistently.)
How can I see if this goal exists? (i.e. list available goals; this question suggests this is impossible.)
How can I change the name of the goal to, for example, foo:bar? (Why does neither display nor time appear anywhere in the XML fragment? How can you tell, from looking at the fragment, what goals it defines?)
To be precise, in foo:bar, foo is the "plugin goal prefix" and bar is the "goal". And while the later is derived from naming conventions (or can be configured1), the former comes from an annotation of the BarMojo, the class that implements the plugin logic. Something like this:
/**
* Do the wonderful bar.
* #goal bar
* #requiresProject false
*/
public class BarMojo extends AbstractMojo
{
...
}
Changing the goal requires modifying the annotation of the mojo of a plugin and rebuilding it.
Regarding the documentation you linked to, there is a clearly mismatch between the goal time and the XML fragment which binds a timestamp goal to the process-test-resources phase. This must be a typo.
How can I manually run this goal? (For similar constructs, the equivalent of mvn display:time sometimes works, but this doesn't work consistently.)
You can call it like this:
mvn com.mycompany.example:maven-touch-plugin:1.0:timestamp
You could make this command shorter by adding com.mycompany.example to the Plugin Groups in your settings.xml (org.apache.maven.plugins and org.codehaus.mojo are declared by default in case you wonder how it works for those plugins)
<settings>
...
<pluginGroups>
<pluginGroup>com.mycompany.example</pluginGroup>
</pluginGroups>
</settings>
Then, because the plugin name matches the ${prefix}-maven-plugin or maven-${prefix}-plugin patterns, you could execute:
mvn touch:timestamp
Following the convention is recommended but, as I said, the prefix can also be configured.
How can I see if this goal exists?
Check the plugin documentation (derived from the plugin sources) or the plugin sources.
1 Note that there is also a typo at the bottom of the mentioned page of the Maven Book. The way to execute the plugin with a custom prefix should be mvn blah:echo (see MVNREF-145).
I think there's a chance that the documentation may have a typo. Plugin goals are specified by plugin-name:goal-name. That XML would bind the goal touch:timestamp to the process-test-resources phase. That fragment doesn't have anything to do with display:time.
As far as I know, it is impossible to rename maven goals. (It seems like it would just make things more confusing.) The plugin source code is what defines goals, not the pom. The <executions> tag in the pom merely allows you to bind plugin goals to phases, or rebind goals if they already have a default phase.
You should be able to run a goal with prefix:goalName. Most often, the prefix is simply whatever is between "maven-" and "-plugin" in the artifactId. e.g. touch:timestamp. This is complicated in a few situations since plugin authors can specify a "goalPrefix" different from the plugin name, but I haven't ever run into problems with this.
The best way to find out what goals a plugin defines, and what phases they are bound to by default is to read the plugin documentation.
To your first one. The name of the goal is defined by the plugin (there is an annotation for that). If have the source code you change that.
Taking a look at the XML you can't know what kind of goals a plugin defines only the ones which are given in the XML. The best location is to look at the documentation of the plugin.
Second one: You have to check the docs. Usually pluginname:goal ...May be you have to specify the full path of the plugin (groupId).
To the third: Usually should be able to use the help plugin take a look at the docs.
How can I change the name of the goal to, for example, foo:bar? (Why does neither display nor time appear anywhere in the XML fragment? How can you tell, from looking at the fragment, what goals it defines?)
To change the name of the prefix to "foo" you need to configure the maven plugin "plugin".
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<goalPrefix>foo</goalPrefix>
</configuration>
</plugin>
To change the name of the goal, you need to edit the javadoc within the plugin java source
/**
* Prints a timestamp to console
*
* #goal bar
*/
public class TimestampMojo extends AbstractMojo {
// ...
}
Add the plugin prefix to your settings.xml file
<pluginGroups>
<pluginGroup>com.mycompany.example</pluginGroup>
</pluginGroups>
How can I manually run this goal?
mvn com.mycompany.example:foo:bar
or with plugin prefix setting (above)
mvn foo:bar
How can I see if this goal exists? (i.e. list available goals)
Add the following to the maven plugin plugin element and you can use foo:help to print out the list of goals.
<plugin>
...
<executions>
<execution>
<id>generated-helpmojo</id>
<goals>
<goal>helpmojo</goal>
</goals>
</execution>
</executions>
</plugin>

Resources