Resuming large Maven releases

I happen to have released large Maven projects with hundreds of modules many times in the past and I am doing it right now as well for Camel Quarkus. The current Camel Quarkus 1.0.0-CR3 release comprises 694 Maven modules. That’s rather big.

The stock knowledge for releasing Maven projects is to use the release plugin, something like

mvn clean release:clean release:prepare release:perform -DreleaseVersion=0.1.0 -DdevelopmentVersion=0.2.0-SNAPSHOT -B

That’s often fine, but when releasing really large source trees, it is rather likely, that something will break - be it network timeouts, repository manager failures, etc. Starting everything anew in such cases can be time consuming and of course the failures may occur again and again so there is no guarantee that some of the release runs will ever finish successfully.

Is there some way to resume a broken release? Yes there is, but let me explain some background information first.

The release:prepare release:perform combo does a couple of things under the hood: Among others, it

  • Calls versions-maven-plugin to set the release version at the beginning and development version at the end of release:prepare

  • Calls maven-scm-plugin to tag the release, to push it and commit the change to the new development iteration, and finally

  • It creates a temporary directory where it freshly checks out your tag and performs something like mvn deploy there.

The last step is what usually fails due to network and other factors you typically do not have under your control. Once you have the git tag in your repo, there is no point performing the first two steps once again. There is also no point in newly uploading the artifacts which were uploaded successfully. All you need to do is the following:

  • Find the artifactId of the module whose deployment failed in the output of the failed release build. Say the artifactId was the-module-where-it-broke.

  • Either find the temporary directory where release:perform run mvn clean deploy it is typically <your-repo-root>/target/checkout

  • If you do not have <your-repo-root>/target/checkout because you e.g. cleaned in between, you can re-build all necessary artifacts using the tag in your main tree. It is important that you activate all profiles that release:perform activates. That’s typically something like -Prelease (or -Papache-release in case ASF projects). Those profiles include generation of source jar, JavaDoc, GPG signing, etc. which are usually skipped during common development builds. So you do something like the following to get what you’d otherwise find in <your-repo-root>/target/checkout:

    cd <your-repo-root>
    git checkout 0.1.0 # the tag you are releasing
    mvn clean package -Prelease -DskipTests
  • Once you have all artifacts built in your source tree, you can resume the deployment where it originally failed:

    # Either
    # cd <your-repo-root>/target/checkout
    # or
    # cd <your-repo-root>
    mvn deploy -Prelease -DskipTests -rf :the-module-where-it-broke

    If it breaks again after a couple of modules, you can resume in the same way, replacing -rf :the-module-where-it-broke with the actual module, where it broke.