Releasing with Maven and Mercurial DVCS

2011-08-14 by mira

How to do a Maven release using Mercurial and getting the release plugin to work with local repository clones.

Distributed Version Control Systems (DVCS) like Git and Mercurial don't need a central master repository. To work with an existing repository (A), the first step is to get a local copy (B) by cloning it. The resulting local clone (B) is a complete, self-contained and independent copy of the original repository (A). A perfect sandbox. Local commits that are made to (B) are not visible in (A) as long as you don't decide to actively push them back to (A).

The Maven release plugin automatically performs several steps to make sure a release can be reproduced from source. I only list the main steps here:

  1. prepare: tagging the code baseline in VCS
  2. perform: clean checkout of tagged baseline from VCS
  3. perform: build, test and deploy to a Maven repository

If a remote VCS is used (e.g. Subversion), the second step fetches the baseline over the network. If the third or any later step fails, a retry beginning at step two will fetch the sources again from VCS over the network. Moreover, during the two-phase release process (release:prepare, release:perform) Maven keeps some control information in temporary files inside the project directory. If you happen to delete those files, for example by reverting, Maven doesn't know anymore that release:prepare was already done (and therefore the VCS has already been tagged).

Lots of opportunities for possible failure exist. By using a DVCS, one can let Maven interact with a temporary local repository. In case of failure, this repository is easily disposable. In case of success, the temporary repository is pushed back to the repository it was cloned from.

mira@apu:~/temp/hg_staging$ hg clone https://bitbucket.org/mira/mira-commons
mira@apu:~/temp/hg_staging$ hg clone mira-commons mira-commons_baseline

mira@apu:~/temp/hg_staging/mira-commons_baseline$ mvn release:prepare release:perform -Dstaging.hg.repo.url=/home/mira/temp/hg_staging/mira-commons

mira@apu:~/temp/hg_staging/mira-commons$ hg push
The location of the staging repository is passed in via the property -Dstaging.hg.repo.url. The relevant section in the POM looks like this:
<project
...
    <scm>
        <connection>scm:hg:http://bitbucket.org/mira/mira-commons</connection>
        <developerConnection>scm:hg:${staging.hg.repo.url}</developerConnection>
        <url>http://bitbucket.org/mira/mira-commons</url>
    </scm>
...        
</project>
My setup is based on this post of Fabrizio Giudici. Fabrizio goes even further and also stages the generated Maven artifacts.

Archive

architecture