Mercurial Maven Release plugin problems - maven-2

I love using Maven and distributed SCMs like Mercurial (BitBucket).
However as I bring my project to scale and my Hg repository grows, I am finding the Maven Release plugin more and more cumbersome to work with.
The primary problem is that when a mvn release:prepare is called Maven doesn't take advantage of the distributed nature of Hg and performs a full clone of the entire repository to put into a temporary directory.
The issue is very well documented by Fabrizio Giudici back in 2009
http://weblogs.java.net/blog/fabriziogiudici/archive/2009/10/29/fixing-two-problems-maven-mercurial-hudson
I would have thought Sonatype might have updated the plugin by now, but alas we are still having to download the entire repo prior to releasing.
I was hoping to reach out to the StackOverflow community to see if anyone else was experiencing this problem and whether anybody has come up with novel ways of solving the dreaded full clone upon a maven release.

This is what I do to avoid the silly multi push to mercurial with maven:
First make sure you use the correct version of the plugin handling the mercurial type of scm via:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<tagNameFormat>#{project.version}</tagNameFormat>
</configuration>
</plugin>
then execute first the prepare goal
mvn release:prepare -DautoVersionSubmodules=true -DreleaseVersion=x.x.x -DdevelopmentVersion=y.y.y-SNAPSHOT -DpushChanges=false
note the pushChanges=false attribute
if all ok then
hg push
mvn release:perform
else
mvn release:clean
and have fun removing the changeset from local hg repo
endif

Related

Unable to download the artifact maven-compiler-plugin from repository

I've created a maven project and wanted to change the java compiler version to 1.6 so I added the ff:
<build>
<plugins>
<plugin>
<artifactId>org.apache.maven.plugins</artifactId>
<groupId>maven-compiler-plugin</groupId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
When I run any maven goal in eclipse, it works. But when I run in terminal I got the ff errors:
Project ID: maven-compiler-plugin:org.apache.maven.plugins
Reason: POM 'maven-compiler-plugin:org.apache.maven.plugins' not found in repository: Unable to download the artifact from any repository
maven-compiler-plugin:org.apache.maven.plugins:pom:2.3.2
from the specified remote repositories:
central (http://repo1.maven.org/maven2),
apache.repo (https://repository.apache.org/content/repositories/releases),
jboss.repo.deprecated (https://repository.jboss.org/nexus/content/repositories/deprecated),
Any idea what's causing this issue?
I was able to solved this issue by updating to maven3. But my problem right now is although I specified maven-compiler-plugin version to be 2.4, I'm still seeing 2.3.2 in the log.
Your groupId and artifactId are reversed.
If Eclipse and the command line create different results, then they use different local Maven repositories. The default is in $HOME/.m2/repository/. So the first step is to find out which one (command line or Eclipse) uses a different local cache and why.
The next question is why the download failed. The usual reason is that Maven tried the download and got an error. Maven will remember the error and not try again. To force it to try again, you have to delete the folder $M2_REPO/repository/org/apache/maven/plugins/maven-compiler-plugin/2.3.2/.
Lastly, when you configure 2.4 but see 2.3.2 in the log, then you're either building the wrong project of one of the POMs of your build overwrites the version for the compiler plugin.
To avoid issues like this, use a parent POM where you keep all the versions in dependencyManagement (for dependencies) and pluginManagement (for plugins) elements. That way, you will never have to define a version in a module POM or in other projects which inherit from this one.
After installing maven 3 from a repository and added maven3 home in /etc/environment what I forgot to do is to reboot my machine, after that it worked.
My /etc/environment now looks like:
M3_HOME="/home/edward/java/apache/maven-3.0.4"
MAVEN_HOME="/home/edward/java/apache/maven-3.0.4"
M3="home/edward/java/apache/maven-3.0.4"
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/edward/java/apache/maven-3.0.4"
Here's how I uninstalled and install maven 3:
http://czetsuya-tech.blogspot.com/2012/05/how-to-install-maven-3-in-ubuntu-1110.html

Attaching Build Number for binaries in Maven

I am running maven build and storing files in Artifactory. One issue I am facing is when ever I try a -snapshot version it overwrites the binary in Artifactory. I tried using the Maven build number plugin, but running in to issues.I reffered to this
http://blog.codehangover.com/track-every-build-number-with-maven/
Describing below What I did?
Updated the masterpom.xml with following line.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.0-beta-3</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
<format>${version}.{0,number}</format>
<items>
<item>buildNumber</item>
</items>
</configuration>
</plugin>
Now I update the pom of ear and webproject as below
<build>
<finalName>${project.artifactId}-${project.version}.${buildNumber}</finalName>
</build>
When I ran mvn clean install, ear and war got generated but when i checked the war inside the ear I am finding it as some thing like war-1.0-SNAPSHOT-null.war. I believe the war and ear couldn't get the buildNumber parameter. I was able to successfully generate the buildNUmber.property files and was able to increment the number by running the buildnumber:create plugin. Here are my questions
What I am doing wrong here and why the buildNumber parameter is not picked.
Also I want to generate all the binaries including jars in the following format binary-version-Snapshot.${buildNumber}. So Do i need to update pom of each file or any other way to update this?
Also we are using Hudson builds for Continous Integration and we want to separate developers builds with Hudson Build number. How can we achieve this if we don't want to checkin the buildNumber.properties after the Hudson build.
To get unique snapshots use the uniqueVersion flag (see James Lorenzen's Blog). If you use the maven goal deploy:deploy-file the uniqueVersion flag is true by default. At my company we have the following policy. Only "official" snapshots go to the repository. A "official" snapshot is one that was build on our reference system (our Jenkins ci server). We don't need the unique feature for snapshots, since we let Jenkins archive the artifacts. This way we can always go back to a certain version if we would like too by using Jenkins. If the build breaks the snapshot will not be deployed to the repo.
To your 2nd question; my understanding is that you need to update every pom file. But since it is a one time change, it shouldn't be too much of a burden.
I am not completely understanding your 3rd question ("... separate developers builds with Hudson Build number..."). In case you want to add the build number for every build done by Hudson, you have several options.
You can add a string as classifier while deploying. Maven will add that classifier in the filename (artifactID-version-classifier.jar - e.g. my.company.calendar-0.0.1-Snapshot-Hudson.jar). The artifact will be retrieved by adding the classifier to the dependency.
add another parameter to your maven call - outputfilename (${project.build.finalName}, see maven docu)
changing your version string to something like

Maven + Mercurial + Site Deploy issues

I'm trying to deploy my Maven generated site to a googlecode project using mercurial.
When I do a
mvn site:deploy
I get Transfer error: org.apache.maven.scm.NoSuchCommandScmException: No such command 'list'.
Its like its trying to do a "svn list" even though I am using mercurial.
In my pom I have maven wagon and mercurial setup (I think correctly):
org.apache.maven.wagon
wagon-scm
1.0-beta-6
org.apache.maven.scm
maven-scm-provider-hg
1.4
Then for my site deploy I have a separate mercurial repository:
<distributionManagement>
<site>
<id>googlecode</id>
<name>googlecode site</name>
<url>scm:hg:${project.site.scm}/</url>
</site>
</distributionManagement>
In my settings.xml I have:
<servers>
<server>
<id>googlecode</id>
<username>...</username>
<password>...</password>
</server>
</servers>
Stumbled upon this question and thought I would provide an answer for anyone else as the documentation for how to do this is sparse:
For quite some time now I've been successfully hosting my website in a Google Code repository that uses Mercurial. It works well and I've had very little issues
First, you have to go to your project, tab "Administer", subtab "Source" and create a new repository called "site". Then, you have to commit and push at least one file, conveniently called "index.html" to that repository because "hg locate", which is called by the SCM plugin, fails on completely empty repositories.
I have this in my POM to deploy to http://site.MYREPO.googlecode.com/hg
<build>
<plugins>
...
<!--Deploy site with Mercurial (Hg)-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.0-beta-3</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-api</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-provider-hg</artifactId>
<version>1.5</version>
</dependency>
</dependencies>
</plugin>
...
</plugins>
</build>
<!--
Distribution
-->
<distributionManagement>
<!--Site deploy repository-->
<site>
<id>MYREPO.googlecode.com</id>
<url>scm:hg:https://site.MYREPO.googlecode.com/hg</url>
</site>
</distributionManagement>
You then have to tell Maven your username and password, so add this to your Maven settings.xml file (note the # character is HTML encoded as Mercurial will choke on it normally)
<settings>
<servers>
<server>
<id>MYREPO.googlecode.com</id>
<username>MYEMAIL%40gmail.com</username>
<password>MYPASSWORD</password>
</server>
</servers>
</settings>
Now you can mvn clean site site:deploy and visit http://site.MYREPO.googlecode.com/hg/index.html to get your complete maven site.
site:deploy uses the scp or file protocol for deploying a site to the server (see here). I configure this along normal ssh lines (authorized_keys, etc). And in the pom have something along the lines:
<!-- The location for generating the website. -->
<distributionManagement>
<site>
<id>website</id>
<url>scp://username#server.com/path/to/deploy/directory/</url>
</site>
</distributionManagement>
It takes everything from the target/site directory and copies it across to the defined destination. However, the downside is, that it is up to me to ensure that what I have deployed is actually checked into my version control system. i.e:
hg push (use mercurial directly to push my changes to other developers).
mvn site:deploy (deploys from my local machine using scp).
First of all, I tried TheLQ's answer and even voted for that one (above), because it works for simple projects, especially if you also add wagon-scm and wagon-ssh dependencies to the maven-site-plugin and update all versions to the latest ;) With a multi-module project though I had an issue: each sub-module's site overwrites previously pushed content instead of nesting them (same problem with mvn deploy, i.e., deploying directly to a Hg managed remote maven repo does not create right folder hierarchy).
Therefore, here is an alternative solution, which also makes less commits to the remote repository (though, it requires a bit of manual work).
First, go to your Google Code project, https://code.google.com/p/MYPROJECT, tab "Administer", "Source" and create a new repository called, e.g., "site" (or how you'd like to call it). Then, you have to commit and push at least one file, conveniently called "index.html" to that repository.
Second, have the following in the parent project's pom.xml (only):
<distributionManagement>
<!-- ... other content ...-->
<site>
<id>MYPROJECT.googlecode.com</id>
<name>MYPROJECT auto-generated site</name>
<url>http://site.MYPROJECT.googlecode.com/hg</url>
</site>
</distributionManagement>
and also -
<url>http://site.MYPROJECT.googlecode.com/hg</url>
Note: Aye, it's "http:" and not "https:"; in my example, the URL is NOT going to be used by Maven to actually deploy the site content there (I am not going to execute site-deploy); instead, will use mvn site site:stage (see below). Also, you do not have to touch the settings.xml (the one in ~/.m2/ on *nix systems).
Third, simply clone the remote ('site') repository to your local machine (target directory can be under the parent project's dir as well as under anywhere else's - just cd to THAT_DIR where you want it):
cd THAT_DIR
hg clone https://USERNAME#code.google.com/p/MYPROJECT.site/
Note: if it existed, you do not have to clone again, just do hg pull, hg update (optionally remove old content using hg rm * and commit). You can also use e.g. free SourceTree software instead of console.
Next, from the projects root, do normally (skip 'clean, install' goals if you did already before; I used Maven 3.0.5):
mvn clean install site site:stage -DstagingDirectory=FullPathTo/MYPROJECT.site
Finally, switch to the clone/stage directory, THAT_DIR/MYPROJECT.site, test the website locally (open index.html in a browser), and if happy do:
hg add *
hg commit -m "re-generated MYPROJECT"
hg push
Check it out at http://site.MYREPO.googlecode.com/hg/index.html and the sources and changes at https://code.google.com/p/MYPROJECT.site/
Done.

Maven repository for Google Code project

I'm hosting a small open source project on Google Code, and I have been asked to submit the jar to a publicly accessible Maven repository. I have almost no practical knowledge of Maven. What would be the best way to do this?
Is there some central repository that I can submit to, or can I host my own? What would I need to do when I want to release a new version of the jar?
I've been Googling and found this, which looks nice and simple, but it seems a bit ... contrary to the spirit of Maven, to commit jar files to SVN :).
Also, would there be a way to still keep track of the download count, as Google Code does?
EDIT
I've been getting some answers, some of which containing hints on what to add to my pom.xml. Thanks guys! But obviously I forgot to mention one important thing: my build script is in ANT, and to put it bluntly, I intend to keep it that way :). I just want to make it easier for Maven users to include my jar in their projects.
The solution I went with in the end
In the end, I did use the solution I referenced before, where I simply commit a Maven repo to SVN. I have the ANT script call Maven to set up the local repo, and then call SVN to commit it to Google Code. For those interested: look at my build script here, in the publish-maven target.
There is a guide to the central repository that has a section on uploading projects that may help. If nothing else you can check the naming conventions and minimal information requirements against your project.
Sonatype also do OSS Repository hosting, see their guide for details.
Update: I'm not saying you should change your build process - if Ant works for you stick with it. It's worth following the Maven conventions in your POM regardless of your build method. As the point of putting your jar in a Maven repository is to make it accessible to Maven users, you will therefore need to define a POM for your published artifact. Following the naming conventions will help your users so you might as well do it. For example adding the SCM details to the pom will (amongst other things) allow your users to import the project into their workspace using the IDE integrations for Maven.
Basically, you have 4 options:
Perform a standard Maven build against a Maven repository (already ruled out)
Set up a Maven repository, do your builds with Ant, and use Maven to deploy the jar and POM.
Set up a Maven repository, ad use an Ant HTTP task to publish the artifacts
Use a Subversion "repository", and use the SvnAnt task to publish the artifacts
Option 1
Use Maven to build and deploy the artifacts (see the Maven book and the above links for details).
Option 2
Assuming you have a build process that creates your jar, and you've defined the POM, your best bet is to publish it to the Sonatype OSS repository as above.
Deploying an existing jar to a standard Maven repository is simple with the Maven deploy plugin's deploy-file goal:
Set up your repository (e.g on the Sonatype servers by raising a Jira request)
Build your jar with Ant.
If you have defined a POM, put it in the same directory as the jar.
Run the deploy-file goal:
mvn deploy:deploy-file -Durl=http://path/to/your/repository\
-DrepositoryId=some.id \
-Dfile=path-to-your-artifact-jar \
-DpomFile=path-to-your-pom.xml
Note that the Maven deploy goal will automatically translate the pom.xml to [project-name]-[version].pom. If you are doing either of the other two alternatives, you will need to ensure you commit the POM with the final name, i.e. [project-name]-[version].pom. You'll also need to ensure you compose the relative paths for the artifacts following the Maven conventions.
E.g. for groupId=com.foo.bar, artifactId=my-project version=1.0.0, the path to the files will be:
/com/foo/bar/my-project/my-project-1.0.0.jar
/com/foo/bar/my-project/my-project-1.0.0.pom
Option 3
If you want to use Ant to deploy to a Maven repository, you can use an Ant HTTP library (Note I've not tried this myself) . You would compose two HTTP put tasks, one for the jar and one for the POM.
<httpput url="http://path/to/your/repository" putFile="/path/to/yourproject.pom">
<userCredentials username="user" password="password"/>
</httpput>
<httpput url="http://path/to/your/repository" putFile="/path/to/yourproject.jar">
<userCredentials username="user" password="password"/>
</httpput>
Option 4
If you want to avoid Maven completely and use Ant to deploy to an SVN-backed repository, you can use the SvnAnt Subversion library. you would simply need to do configure the Svn import task to add your artifacts to the Remote Subversion repository.
<import path ="/dir/containing/the/jar/and/pom"
url="svn://your/svn/repository"
message="release"/>
Check wagon-svn. It will allow you to 'deploy' to a Subversion repository. It's a little convoluted, but it's better than nothing. I know of a few projects that use it at java.net, and I also came across some projects using it at code.google.com.
If you want to use it, then you first need to load wagon-svn as an extension:
<build>
...
<extensions>
<extension>
<groupId>org.jvnet.wagon-svn</groupId>
<artifactId>wagon-svn</artifactId>
<version>...</version>
</extension>
</extensions>
Next, you need to set your deployment targets using the svn: protocol identifier. Here's an example I copied from the Internet.
<distributionManagement>
<repository>
<id>maven-config-processor-plugin-repo-releases</id>
<name>Maven Repository for Config Processor Plugin (releases)</name>
<url>svn:https://maven-config-processor-plugin.googlecode.com/svn/maven-repo/releases</url>
<uniqueVersion>false</uniqueVersion>
</repository>
<snapshotRepository>
<id>maven-config-processor-plugin-repo-releases</id>
<name>Maven Repository for Config Processor Plugin (snapshots)</name>
<url>svn:https://maven-config-processor-plugin.googlecode.com/svn/maven-repo/snapshots</url>
<uniqueVersion>false</uniqueVersion>
</snapshotRepository>
</distributionManagement>
Check if the Maven repository support maven deploy plugin. This would be the easiest approach.
Most repositories uses ssh as the transport. See this for details.
Once it's setup, all you have to do is:
mvn deploy:deploy
You can submit your jar to https://clojars.org/
In your pom.xml:
<repositories>
<repository>
<id>clojars.org</id>
<url>http://clojars.org/repo</url>
</repository>
</repositories>

How can I configure Maven to commit to a Mercurial repository when I install:install

Maven's SCM plug-in doesn't appear to provide a "commit" goal. scm:checkin performs a commit AND push. I need to avoid the push.
I'm simply interested in doing an hg commit during install:install. I'm not using the release plugin and don't need it yet. I'm simply working locally in a multi-module environment and want to ensure that my source repository aligns with my Maven locally-installed snapshots for each module. In other words, every time I install a new snapshot of a module, I want the related code committed to hg to make every snapshot directly correlate to an hg revision (or range of revisions when multiple commits occur between snapshots).
The following will bind scm:checkin to the install phase. As long as the repository is a file:// scheme (at least for Mercurial, according to the code), a push is not performed during scm:checkin.
Define properties used in the following steps:
<properties>
<message>maven install:install auto-checkin.</message>
<repository.local>file:///path/to/local/repository</repository.local>
<repository.type>hg</repository.type>
</properties>
The <message> can be anything you choose. It isn't ideal to be completely fixed as commits should include meaningful messages as to what changes were made. But, I do believe there should be a standard message included in auto-commits to identify it as such. Just modify the <message> property from step 1. before each install.
This is just a standard scm node for a Maven-based project. Since this is concerned only with a local repository, the URLs are all the same.
<scm>
<connection>scm:${repository.type}:${repository.local}</connection>
<developerConnection>scm:${repository.type}:${repository.local}</developerConnection>
<url>scm:${repository.type}:${repository.local}</url>
</scm>
This is plug-in that runs during the install phase that performs the commit. It'll simply execute the proper scm checkin based on the definition in step 2.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>checkin</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
One problem is that I receive the following.
DEPRECATED: Binding aggregator mojos
to lifecycle phases in the POM is
considered dangerous. This feature has
been deprecated. Please adjust your
POM files accordingly.
I'm looking into how to resolve it but, for now, it works and I'm going with it.
What about setting the connectionUrl on the checkin to a throw-away repository on the local box? So your checkout would come from the "central" repo, but your 'checkin' would go only to the working repository (the commit that you want) and the (apparently) unavoidable push would go to file:///tmp/whocares.
Alternately there's probably a single line of code in the scm plugin to comment out to avoid that push.
Maven's scm plugin doesn't appear to provide a "commit" goal. scm:checkin performs a commit AND push. I need to avoid the push.
Then the scm plugin is maybe not what you're looking for :)
I'm simply interested in doing an hg commit during install:install. I'm not using the release plugin and don't need it yet.
To be honest, this is a pretty odd usage. While I understand what you described, it doesn't really make sense to me to "sync" a SNAPSHOT with a revision number. Even if you don't commit code between two SNAPSHOT builds, I don't understand how this can this be a problem. In other words, I don't see what is the added value of forcing the commit. And using the release plugin won't solve anything in my opinion.
To summarize, I don't think that the scm plugin will allow you to achieve your goal (at least not without hacking). I don't know if there is mercurial support in Ant but, if there is, maybe you should look in this direction instead (and use the antrun plugin).