Maven prevent build if there is uncommitted changes - java

Is there any way to check if there is not committed files or untracked files in git repo and prevent maven build?
I mean if I run
mvn install
And install should fail with warning that there is something to commit.
I need this because I want to know hash of commit which corresponds to some builded .war file. Sometimes I forgot to commit changes and build .war file, and as a result I can't reproduce this build exactly as it was.

Generally these kinds of problems are resolved by never building releases out of developer workstations.
One way to avoid that is to have a single machine where the git repository is pulled into a clean directory, and the build is launched from there. Then you always use the "mainline build" for your testing and deployment.
Jenkins is an automated tool that drives clean builds as described above. There are other tools available, but Jenkins is the most popular.
The best way to know if you have everything committed is to run a git status and read the response. However, even with that understanding, it is very easy to forget to push your commit into the origin, and when you do push it, there is also a chance that you merged commits. In short, you might have to just take more care in your process, instead of relying on tools to take care for you.

One can use a git hook to accomplish this; I would use something like a jenkins or hudson to accomplish this, but since you asked about using git, the hook should look like:
# pre-commit
git diff || true
Mark it as executable and you should be golden.

For modified (but not for untracked) files, Maven SCM plugin can help you, specifically scm:check-local-modification
Add this to the plugins section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.11.2</version>
<executions>
<execution>
<goals>
<goal>check-local-modification</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
Chose the phase carefully to define where you want the build to stop if there are local modifications. The above example would prevent any compilation. If you want to be able to compile the modified code, consider setting the phase to package. That way, you would be able to compile and unit test the modified code, but not to package it to a jar file.

Related

Maven Plugin for project semantic versioning

I'm looking for a maven plugin that will help me manage version names and codes of every build that is made on our CI environment. Something that will be able to attach a prefix to the main version code or even update it (not changing the pom.xml). For example:
project version: 2.0.1
git/svn revision: 2342334
jar output: name-2.0.1-2342334.jar
maven repo: ../path/to/local/maven/repo/<package path>/2.0.1-2342334/
The main requirements to this plugin are:
Must be in Maven Repository (which means that NO additional setting required to add this plugin in my pom.xml and run maven)
Must not edit the pom, each time it's applied
A configuration file, would be great, so I could manage the versioning process
Must be able to edit the output file metadata (so the version will be applied as if it was written in the pom.xml file in the first place)
So far I found only maven-buildmetadata-pluging but unfortunately it's not in Maven Repo, so I'm stuck. Any help would be great.
Hosting your own maven repository is very easy, using either Nexus or Artifactory. You can also use the Artifactory cloud version (I'm not affiliated with them...) so it may solve your problem. BTW - a simple server with Apache does the trick as well, but with more work..,
Regarding the plugins: If you deploy snapshot applications then each gets its own version based on timestamp.
For releases another option is to run an svn info and put the result (or part of it) into the generated artifact. The information can then be accessed by the code.
If you change the version of your artifact the pom has to reflect the change, cause otherwise it's not reproducible.
If you change something in your build process (like added versions, whatever) it has to be reflected in the pom file. Otherwise you can not reproduce the build process with the same result.
You have written not to change the pom file but maintaining a separate file. So the questions is: Why not using the pom file itself, cause it's intended exactly for that purpose.
Furthermore all informations which you mentioned by the maven-buildmetadata-plugin can be achived by using existing maven plugins (like build-helper-maven-plugin, buildnumber-maven-plugin).
The SCM information can be used by using the buildnumber-maven-plugin which provides information like SCM revision number (SVN or GIT hash).
An on the other hand if you don't like to change your pom file manually you can use either the versions-maven-plugin or the maven-release-plugin which automatically can change informations in your pom file and handle all these things automatically.
To maintain metadata in your producted artifacts you can configure all plugins (like ear, war, jar) etc. more or less like this where the buildNumber is comming from buildnumber-maven-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<archive>
<addMavenDescriptor>true</addMavenDescriptor>
<index>true</index>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<artifactId>${project.artifactId}</artifactId>
<groupId>${project.groupId}</groupId>
<version>${project.version}</version>
<buildNumber>${buildNumber}</buildNumber>
</manifestEntries>
</archive>
</configuration>
</plugin>
And of course if you really like to use Maven you should have to use an repository manager as already mentioned like Artifactory or Nexus which make life easier.
I just would like to add (although the question is 5 years old and already has an accepted answer) that the Buildmetadata Maven Plugin was not available on the Maven Repo at first, but it is now (since late 2013). People who would like to give it a try find the artifact at the following locations :
com.redhat.rcm.maven.plugin:buildmetadata-maven-plugin
de.smartics.maven.plugin:buildmetadata-maven-plugin
Please note that the name has changed from maven-buildmetadata-plugin to buildmetadata-maven-plugin due to naming conventions.
I'm one of the "original" authors of this plugin at smartics. If you would like to use it, you probably would like to use the fork provided by Red Hat. To my knowledge the two versions do not differ very much and they have not been synced since there is just so much other stuff to do and the plugin seems to be feature stable. ;-)
The source code for both versions is also available on GitHub:
release-engineering/buildmetadata-maven-plugin
smartics/buildmetadata-maven-plugin
As already stated, you have to change the version in the pom. One way of doing that, in combination with the release plugin is:
mvn \
se.bjurr.gitchangelog:git-changelog-maven-plugin:VERSION_HERE:semantic-version \
release:prepare release:perform
Using Git Changelog Maven Plugin

Antlr4 "Test Rig" and maven

I am struggling a little bit to figure out how I can use the antlr4 maven plug in to run the TestRig class?
I've read though the output of mvn antlr4:help -Ddetail=true, which is the only documentation I have been able to find, but this doesn't mention how to use the TestRig. So, what's the recommended way of using the test rig together with maven? using the grun alias method doesn't seem very elegant here.
UPDATED - Reasoning
Hello :)
Right, don't get me wrong but I really don't understand why you wouldn't want this functionality in the maven plugin? And I don't understand why its soul purpose should be to compile grammars?
Currently, if I maintain a build with Maven, and I use the antlr4-maven-plugin , it will install both the plugin and the antlr 4.1 in my maven repository. With this already there, why would I start adding things to my classpath and creating aliases when maven can take care of that? I mean, this is what maven is for really. If I had a antlr4:TestRig goal, then all I would do was use that. No need to manually maintain the class path, or create bash aliases. It would just work.
And be far far more elegant that hard-coding elements from my local maven repository in my class path, and maintaining bash aliases. Or alternatively, maintain two installations per. version of antlr I wish to use (one maintained by me, simply to use TestRig, and one maintained by maven for everything else).
Additionally, if I wanted to use a different version of antlr, then I wouldn't need to update the classpath and my aliases, maven would simply manage all this for me :)
This is how I invoke TestRig with Maven:
mvn exec:java -Dexec.mainClass="org.antlr.v4.runtime.misc.TestRig"
-Dexec.args="<DOT_NOTATION_GRAMMAR_CLASSPATH> <START_RULE>
-gui <INPUT_FILE>"
So if you've got MyGrammar.g4 in src/main/antlr4/com/test/parser with a starting rule of startRule:
mvn exec:java -Dexec.mainClass="org.antlr.v4.runtime.misc.TestRig"
-Dexec.args="com.test.parser.MyGrammar startRule
-gui <INPUT_FILE>"
I had a similar question, in that I wanted to use the TestRig -gui option for debugging my grammar. I didn't find a way to run the GUI via the antlr4-maven-plugin, but I did manage to build a satisfactory CLASSPATH. The key was to include target/classes.
# Assuming your project is in $PROJECT ..
CLASSPATH=".:/usr/local/lib/antlr-4.1-complete.jar:$PROJECT/target/classes"
alias grun='java org.antlr.v4.runtime.misc.TestRig'
mvn -q compile
grun MyGrammer startingRule -gui < test_input
Should produce a lovely GUI view of the syntax tree.
Why would the Maven plugin run the TestRig class? The Maven plugin's job is converting the .g4 grammar files to .java source files in the proper package locations and ensuring those generated files get compiled. TestRig is not used for any part of that.
Edit: I have been using ANTLR for many years, in many applications. In all that time I have never updated my system classpath, nor operated ANTLR/gunit/TestRig from the command line or created aliases for it. Doing so is not helpful for automated testing and inevitably leads users into the problems you described. That said, the thought that TestRig needed special support in the Maven plugin also never crossed my mind, because better solutions already exist.
Some alternatives
You can use the surefire plugin, and write a JUnit test that performs operations on your grammar directly (create a lexer/parser, parse some input, and perhaps even call inspect() on the resulting parse tree.
You can use the surefire plugin, and write a JUnit test that explicitly calls TestRig.main(String[]) with the correct arguments.
You can modify the ANTLR 4 Maven plugin to add a new goal for running TestRig, and submit a pull request to the project to have it included in a future release (you would need to make a very compelling case since there are already 2 alternatives that are more suited to long-term successful testing of a project using ANTLR 4).
I like the idea of using Maven to run the TestRig. But I do not like to add the dependency org.antlr:antlr4 to my code (because I already have org.antlr:antlr4-runtime) so my solution is to configure the exec plugin with an additional dependency.
<properties>
<antlr.version>4.7.1</antlr.version>
</properties>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>TestRigGui</id>
<phase>none</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.antlr.v4.gui.TestRig</mainClass>
<arguments>
<!-- Grammar -->
<argument>de.humanfork.experiment.antlr.Hello</argument>
<!-- start rule -->
<argument>hello_rule</argument>
<!-- enable gui -->
<argument>-gui</argument>
<!-- input file -->
<argument>example.txt</argument>
</arguments>
<includePluginDependencies>true</includePluginDependencies>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>${antlr.version}</version>
</dependency>
</dependencies>
</plugin>
Then use: mvn exec:java#TestRigGui to start the GUI
BTW: in ANTLR 4.7.1 the TestRig main class is: org.antlr.v4.gui.TestRig

Eclipse/Maven and "Resolve dependencies from workspace projects" can't mix jars and source?

I've got what seems like a corner case for Eclipse/Maven and "Resolve dependencies from workspace projects". My project has a mix of written code and generated code, with the generated code coming from a dependency which uses JAXWS.
The problem is that if I check "Resolve dependencies", Eclipse/Maven ignores any JAR dependencies and tries to resolve everything by only looking at the workspace, which results in Eclipse showing errors like "Package/Class not found" (related to the generated code) even though the project will build fine with Maven from the command line.
On the other hand, if I uncheck it, it resolves everything by only looking at the JARs in the Maven repository. The second option generally works, but when I do something like Ctrl-click on a class or variable, I get the Class File Editor and "Source not found", which isn't terribly useful. Also, it can get out of sync if I edit code in the IDE but don't run "maven install" after that.
I suppose this is mainly an inconvenience with Eclipse but it's annoying. I am considering resolving this by modifying the Maven dependencies to build with source (or debug) but I can't necessarily do this with everything. Is the "Resolve dependencies" option intended to work exclusively one way or the other as I've described?
You might want to have a look at the build helper maven plugin.
You can configure it like this :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated-sources</source>
<source>target/jaxws/wsimport/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
This will tell your eclipse maven plugin to have a look at the generated sources and include it in your project classpath.
You can also add the generated sources manually to your classpath in eclipse. (right-click on the generated folder -> add to build path)
I think that since you want to reference files that only exist after a build that you somehow force the build to happen before you need the references resolved. You could cheat by just doing a build from within Eclipse. That would leave the generated source files in place ready to be referenced. I think, however, that the maven philosophy would have you move the generated code to another maven artifact entirely. That would let you separate the lifecycle of the two groups of code so that when you're ready to use Eclipse to edit the hand-coded code, references to generated classes are resolved because you've already generated that code in the build of an separate, independent module.
I know this is an old issue. But I encountered the same thing in Juno with an updated "m2e-wtp" plugin. So I'm answering solely for other readers' benefit.
This was only happening in war projects. The only thing resolved it eventually was removing the ".settings" folder under the war project's folder and restarting eclipse.

Log statements in pom.xml or Tracking flow of Maven

I am new to Maven and I am trying to get strong hold of it. I have gone through the beginner's tutorials and I am able to understand the basic stuff, but I have a complex pom.xml file in my project and my next goal is to understand that.
With the limited knowledge acquired from beginner's guide it is not possible for me to understand that complex pom.xml, so i was thinking of adding some sort of log statements in pom.xml or looking for an alternative via which i could track the flow of execution in pom.xml, since that would help me in knowing how things are moving.
You could printout some log messages to maven console using the maven-antrun-plugin, you can also specify the phase you want to print the message in, see the code below (it goes to the plugins section)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>print-log</id>
<phase>initialize</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo message="Your log message for project ${project.artifactId}" />
</target>
</configuration>
</execution>
</executions>
</plugin>
I believe that output generated by debug option in maven can be quite huge and time consuming for reading. I use it only for some specific problem analysis.
For me it allways worked to go through complicated pom.xml files by reading and try to understand intent of the author of the particular section (I think good reference for the pom.xml elements can be found on: http://maven.apache.org/pom.html).
Once you run build afterwards, you can see what and when is it executed and you can find mapping between what you've learned before and how it really works :)
You can start by issuing
mvn -X install
That will give you the flow of execution.
According to mvn --help:
-X,--debug Produce execution debug output
An alternative if you want to see all your dependencies, properties, plugins, directories etc. the try this:
mvn help:effective-pom
I would recommend to read more about Maven build lifecycle. Maven is not a script-like build automation tool (like ant or make). It's a different approach. Logs should be less important than output artifacts produced in ./target directory.

How can I test a maven archetype that I've just created?

I've created a few archetypes for a project that work fine for now, but I'd like to be able to verify that the code generated from the archetypes continues to work in the future.
What I'd like is a phase of the archetype build that takes the archetype just created, runs mvn archetype:generate on it, and then runs mvn verify on the generated code to verify that the generated code is actually OK. If need be I'll write my own mojo to do this, but wanted to see if a solution already exists. I see the archetype:integration-test goal, but it doesn't seem to be doing what I want.
UPDATE 2013: This is now much easier than the other answers suggest.
https://issues.apache.org/jira/browse/ARCHETYPE-334 was completed in Aug 2011
To use, simply place the word install inside the goal.txt file mentioned above, and the tests from the project you are archetyping will be invoked as part of a normal build. (And/or verify in the case of OP.)
However, if you new to making archetypes be aware that this popular mini-guide is out of date and, while it will work for making an archetype it will not work for having archetype integration tests run. You should instead be creating an archetype-metadata.xml file as described here. (This is much nicer to work with as well, as it uses file sets!)
Also note these integration tests do not respond to -DskipTests but this can be remedied as follows:
<build>
<plugins>
<plugin>
<artifactId>maven-archetype-plugin</artifactId>
<version>2.2</version>
<configuration>
<skip>${skipTests}</skip>
</configuration>
</plugin>
</plugins>
</build>
(Although this looks like it skips the entire plugin, it actually works, probably because it falls back to a legacy mode; whereas I could not find any successful way to skip just the integration-test goal execution using code above.)
beside the the approach of using the maven-invoker-plugin, we are using a different approach. With the help of the Maven Verifier you can test your maven plugins and archetypes easily.
Just add the following dependency into your pom of your maven test project:
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-verifier</artifactId>
<version>1.2</version>
</dependency>
Now you are able to use
org.apache.maven.it.Verifier
into your normal JUnit Tests. With the verifier you can run maven goals and some assertions about the result.
For a complete example just check out the integration test maven modules of our javascript-archetypes:
https://github.com/akquinet/javascript-archetypes
I was struggling a little with this myself, and figured that when using current v2.3 of the maven-archetype-plugin, in addition to a src/test/resources/projects/first/goal.txt, one also needs a src/test/resources/projects/first/archetype.properties containing something like this:
sourceEncoding=UTF-8
groupId=integrationtest.group
artifactId=integrationtest.artifactId
version=1.0.0-SNAPSHOT
package=org.eclipse.xtend.xtend-archetype.integrationtest
packageInPathFormat=org/eclipse/xtend/xtend-archetype/integrationtest
This pull request illustrates a complete working example.
I see the archetype:integration-test goal, but it doesn't seem to be doing what I want.
Unless I misunderstood what you want, the archetype:integration-test goal seems to be a very good solution:
Execute the archetype integration
tests, consisting of a creation of a
project from the current archetype
with defined properties and optional
comparison with reference copy. An IT
consists of a directory in
src/test/resources/projects
containing:
goal.txt (content actually not used, but future version should interpret it
as a goal to run against the generated
project: see ARCHETYPE-334),
archetype.properties with properties for project generation,
optional reference/ directory containing a reference copy of the
expected project created from the IT.
According to the above description, this goals allows precisely to run Integration Test(s) to check a project generated with the current archetype against an expected result and this looks like a clean, simple, self contained way to test an archetype.
Why is this approach not satisfying? What did I miss?
I guess that would be a scenario for a continuous integration server like hudson.
You'd define a job that
empties a directory (shell script)
creates a new project based on the archetype (mvn archetype:generate)
runs the project (mvn package)
While this could probably somehow be fit into one maven lifecycle, it would feel like an awful mess. Use CI instead.

Categories