Fixing two problems with Maven + Mercurial + Hudson: second take
In the past weekend I've been able to improve the settings for
automated Maven releases that
href="http://weblogs.java.net/blog/fabriziogiudici/archive/2009/10/29/fixing-two-problems-maven-mercurial-hudson">I've
blogged about about ten days ago. Peter Mount
href="http://www.retep.org/2009/11/releasing-to-kenai-via-maven.html">complemented
the information with some practical examples on how to use
that stuff invoking Maven with the proper parameters. I've been able to
significantly clean up and improve the Maven configuration, so now a
staged release can be performed exclusively with a sequence of Maven
invocations, specifying profiles instead of a complicated set of
parameters. And I'll show you how to fit it better with a CI
environment such as Hudson.
I'm not repeating the concepts behind this stuff, that have been
href="http://weblogs.java.net/blog/fabriziogiudici/archive/2009/10/29/fixing-two-problems-maven-mercurial-hudson">explained
in my previous post, but just showing you the relevant
sections of the POM.
First, the SCM URL is defined by means of a property, which is
style="font-family: monospace;">hg.repo.url,
whose value has a default in the properties section:
<scm>
style="font-family: monospace;">
<connection>scm:hg:http://kenai.com/hg/forceten~src</connection>
style="font-family: monospace;">
<developerConnection>scm:hg:${hg.repo.url}</developerConnection>
style="font-family: monospace;">
<url>http://kenai.com/projects/forceten/sources/src/show</url>
style="font-family: monospace;">
</scm>
style="font-family: monospace;">
<properties>
style="font-family: monospace;">
<hg.repo.url>https://kenai.com/hg/forceten~src</hg.repo.url>
style="font-family: monospace;">
<staging.mvn.repo.url>file://${project.build.directory}/target-maven-repo</staging.mvn.repo.url>
style="font-family: monospace;">
</properties>
Then you define a
style="font-family: monospace; font-weight: bold;">“release”
profile which is used to create the staged release, that is to have a
local pair of (Maven;Mercurial) repositories populated with all the
relevant artifacts. The profile overrides and defines some properties,
such as hg.repo.url
and altDeploymentRepository,
that make Maven point to the staging repositories; furthermore it
installs during the initialization phase a couple of goals that scratch
and create the relative directories under the
style="font-family: monospace;">target folder
(the staging Mercurial repo is also initialized). There's still a minor
issue, in the fact that those directories are created for every module,
not only for the main directory, in spite of the
style="font-family: monospace;">inherited=false
property (which seems to be severely broken with Maven, or at least
obscure).
<profile>
style="font-family: monospace;">
<id>release</id>
style="font-family: monospace;">
<properties>
style="font-family: monospace;">
style="font-family: monospace;">
<hg.repo.url>file://${project.build.directory}/dummy-hg-repo</hg.repo.url>
style="font-family: monospace;">
style="font-family: monospace;">
<altDeploymentRepository>release-repo-hudson::default::${staging.mvn.repo.url}</altDeploymentRepository>
style="font-family: monospace;">
</properties>
style="font-family: monospace;">
<build>
<plugins>
style="font-family: monospace;">
<plugin>
style="font-family: monospace;">
<groupId>org.codehaus.mojo</groupId>
style="font-family: monospace;">
<artifactId>exec-maven-plugin</artifactId>
style="font-family: monospace;">
<executions>
style="font-family: monospace;">
<execution>
style="font-family: monospace;">
<id>clean-release-dirs</id>
style="font-family: monospace;">
<phase>initialize</phase>
style="font-family: monospace;">
<goals>
<goal>exec</goal>
style="font-family: monospace;">
</goals>
style="font-family: monospace;">
<inherited>false</inherited>
style="font-family: monospace;">
<configuration>
style="font-family: monospace;">
<executable>rm</executable>
style="font-family: monospace;">
<arguments>
style="font-family: monospace;">
<argument>-rf</argument>
style="font-family: monospace;">
<argument>${project.build.directory}/dummy-hg-repo</argument>
style="font-family: monospace;">
<argument>${project.build.directory}/target-maven-repo</argument>
style="font-family: monospace;">
</arguments>
style="font-family: monospace;">
</configuration>
style="font-family: monospace;">
</execution>
style="font-family: monospace;">
<execution>
style="font-family: monospace;">
<id>create-release-dirs</id>
style="font-family: monospace;">
<phase>initialize</phase>
style="font-family: monospace;">
<goals>
<goal>exec</goal>
style="font-family: monospace;">
</goals>
style="font-family: monospace;">
<inherited>false</inherited>
style="font-family: monospace;">
<configuration>
style="font-family: monospace;">
<executable>mkdir</executable>
style="font-family: monospace;">
<arguments>
style="font-family: monospace;">
<argument>-p</argument>
style="font-family: monospace;">
<argument>${project.build.directory}/dummy-hg-repo</argument>
style="font-family: monospace;">
<argument>${project.build.directory}/target-maven-repo</argument>
style="font-family: monospace;">
</arguments>
style="font-family: monospace;">
</configuration>
style="font-family: monospace;">
</execution>
style="font-family: monospace;">
<execution>
style="font-family: monospace;">
<id>init-dummy-hg-repo</id>
style="font-family: monospace;">
<phase>initialize</phase>
style="font-family: monospace;">
<goals>
<goal>exec</goal>
style="font-family: monospace;">
</goals>
style="font-family: monospace;">
<inherited>false</inherited>
style="font-family: monospace;">
<configuration>
style="font-family: monospace;">
<executable>hg</executable>
style="font-family: monospace;">
<workingDirectory>${project.build.directory}/dummy-hg-repo</workingDirectory>
style="font-family: monospace;">
<arguments>
style="font-family: monospace;">
<argument>init</argument>
style="font-family: monospace;">
</arguments>
style="font-family: monospace;">
</configuration>
style="font-family: monospace;">
</execution>
style="font-family: monospace;">
</executions>
style="font-family: monospace;">
</plugin>
style="font-family: monospace;">
</plugins>
style="font-family: monospace;">
</build>
style="font-family: monospace;">
</profile>
A second profile,
style="font-weight: bold; font-family: monospace;">“release-commit”,
performs both a Mercurial push from the staging repository and also
invokes the wagon-maven-plugin:merge-repo
goal, which synchronize the real Maven repository with the new
artifacts:
<profile>
style="font-family: monospace;">
<id>release-commit</id>
style="font-family: monospace;">
<build>
<plugins>
style="font-family: monospace;">
<plugin>
style="font-family: monospace;">
<groupId>org.codehaus.mojo</groupId>
style="font-family: monospace;">
<artifactId>exec-maven-plugin</artifactId>
style="font-family: monospace;">
<executions>
style="font-family: monospace;">
<execution>
style="font-family: monospace;">
<id>push-hg</id>
style="font-family: monospace;">
<phase>initialize</phase>
style="font-family: monospace;">
<goals>
<goal>exec</goal>
style="font-family: monospace;">
</goals>
style="font-family: monospace;">
<inherited>false</inherited>
style="font-family: monospace;">
<configuration>
style="font-family: monospace;">
<executable>hg</executable>
style="font-family: monospace;">
<arguments>
style="font-family: monospace;">
<argument>push</argument>
style="font-family: monospace;">
</arguments>
style="font-family: monospace;">
</configuration>
style="font-family: monospace;">
</execution>
style="font-family: monospace;">
</executions>
style="font-family: monospace;">
</plugin>
style="font-family: monospace;">
<plugin>
style="font-family: monospace;">
<groupId>org.codehaus.mojo</groupId>
style="font-family: monospace;">
<artifactId>wagon-maven-plugin</artifactId>
style="font-family: monospace;">
<configuration>
style="font-family: monospace;">
<source>${staging.mvn.repo.url}</source>
style="font-family: monospace;">
<target>${project.distributionManagement.repository.url}</target>
style="font-family: monospace;">
<targetId>${project.distributionManagement.repository.id}</targetId>
style="font-family: monospace;">
</configuration>
style="font-family: monospace;">
<executions>
style="font-family: monospace;">
<execution>
style="font-family: monospace;">
<id>merge-repo</id>
style="font-family: monospace;">
<phase>initialize</phase>
style="font-family: monospace;">
<goals>
<goal>merge-maven-repos</goal>
style="font-family: monospace;">
</goals>
style="font-family: monospace;">
<inherited>false</inherited>
style="font-family: monospace;">
</execution>
style="font-family: monospace;">
</executions>
style="font-family: monospace;">
</plugin>
style="font-family: monospace;">
</plugins>
style="font-family: monospace;">
</build>
style="font-family: monospace;">
</profile>
A third profile,
style="font-family: monospace; font-weight: bold;">“release-cancel”,
can be used in alternative to “release-commit”
to throw away everything that has been prepared for the release,
perhaps because we only wanted to run a test. It basically scratches
the local Mercurial repository, so you have to clone it again from the
main remote repository. This could be improved, by just stripping (by
means of the hg
strip command) the local commits that haven't be pushed
again, but I haven't found so far a simple way to detect the revision
number to strip from (and unfortunately it seems there's no such a
thing as a “strip all local commits” in Mercurial).
<profile>
style="font-family: monospace;">
<id>release-cancel</id>
style="font-family: monospace;">
<build>
<plugins>
style="font-family: monospace;">
<plugin>
style="font-family: monospace;">
<groupId>org.codehaus.mojo</groupId>
style="font-family: monospace;">
<artifactId>exec-maven-plugin</artifactId>
style="font-family: monospace;">
<executions>
style="font-family: monospace;">
<execution>
style="font-family: monospace;">
<id>strip-hg</id>
style="font-family: monospace;">
<phase>initialize</phase>
style="font-family: monospace;">
<goals>
<goal>exec</goal>
style="font-family: monospace;">
</goals>
style="font-family: monospace;">
<inherited>false</inherited>
style="font-family: monospace;">
<configuration>
style="font-family: monospace;">
<!-- FIXME: would be better to strip local changes -->
style="font-family: monospace;">
<executable>rm</executable>
style="font-family: monospace;">
<arguments>
style="font-family: monospace;">
<argument>-rf</argument>
style="font-family: monospace;">
<argument>.hg</argument>
style="font-family: monospace;">
</arguments>
style="font-family: monospace;">
</configuration>
style="font-family: monospace;">
</execution>
style="font-family: monospace;">
</executions>
style="font-family: monospace;">
</plugin>
style="font-family: monospace;">
</plugins>
style="font-family: monospace;">
</build>
style="font-family: monospace;">
</profile>
At last, you need to configure the release plugin so the
style="font-family: monospace;">“release”
profile is correctly propagated:
<plugin>
style="font-family: monospace;">
<groupId>org.apache.maven.plugins</groupId>
style="font-family: monospace;">
<artifactId>maven-release-plugin</artifactId>
style="font-family: monospace;">
<configuration>
style="font-family: monospace;">
<preparationGoals>clean install
verify</preparationGoals>
style="font-family: monospace;">
<goals>clean install javadoc:javadoc assembly:assembly
deploy</goals>
style="font-family: monospace;">
<arguments>-Prelease
-DaltDeploymentRepository="${altDeploymentRepository}"</arguments>
style="font-family: monospace;">
</configuration>
style="font-family: monospace;">
</plugin>
Small tip: note that we are passing
style="font-family: monospace;">altDeploymentRepository
- one could wonder why, as it would be automatically re-defined by the
forked Maven invocation. The reason is that its definition is relative
to the current working directory (e.g.
style="font-family: monospace;">target/something)
so the re-definition in the forked Maven would set it to
style="font-family: monospace;">target/checkout/target/something.
My Hudson job is now configured with a sequence of two Maven
invocations:
mvn -B -Prelease
clean install release:clean release:prepare release:perform
style="font-family: monospace;">
mvn -N
-P${RELEASE_MODE} initialize
The Hudson job is configured with a parameter named
style="font-family: monospace;">RELEASE_MODE
which is used to choose whether you want to perform a true release or a
test one.
src="http://www.java.net/sites/default/files/FirefoxScreenSnapz004.png">
I've done also a couple more refinements which prove useful in a Hudson
environment, but it's a matter of another post.
You can see the real-world Hudson configuration
href="http://hudson.tidalwave.it/hudson/job/ForceTen%20Release/configure">here
(if the link is broken, try to remove the /hudson part); you can also
href="https://kenai.com/website/forceten/maven-repository/releases/it/tidalwave/geo/forceten/0.5.0/forceten-0.5.0-project.tar.gz">download
the related projects sources.
- Login or register to post comments
- Printer-friendly version
- fabriziogiudici's blog
- 3641 reads





