Releasing A Maven Project

What follows is a description of releasing a Maven project to a staging repository, whereupon it is scrutinized by the community, approved, and transferred to a production repository.

Prerequisites

Be sure that:

  • you have all Maven servers defined in your settings.xml. For more information, please refer to Committer settings.
  • you have created your GPG keys. For more information, please refer to Making GPG Keys.
  • you have a GPG client installed and on your shell's path. See http://www.gnupg.org/.
  • you have a Subversion 1.5+ client installed and on your shell's path. See http://subversion.tigris.org/.
  • you have a Java 1.4.2 JDK installed and on your shell's path. See http://java.sun.com/j2se/1.4.2/download.html.
  • you have set the environment variable MAVEN_OPTS=-Xmx512m
  • you are using Maven 2.0.x (or 2.2.x), as Maven 2.1.x is known to produce wrong gpg pom signatures (see MGPG-14).

Formerly, a release profile was required in the ${user.home}/.m2/settings.xml to define the staging repository. As of inheritance from the Apache parent POM version 5, a repository manager will automatically handle staging (see below for details). Hence, configuration of deploy.altRepository is no longer necessary and should be removed from your existing release profile.

Here's what your release profile might look like in your ${user.home}/.m2/settings.xml:

<settings>
  ...
  <profiles>
    <profile>
      <id>apache-release</id>
      <properties>
        <gpg.passphrase> <!-- YOUR KEY PASSPHRASE --> </gpg.passphrase>
      </properties>
    </profile>
  </profiles>
  ...
</settings>

Everything that you need to release has been configured in the POM all Maven projects inherit from. The release plugin configuration being used is the following:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-release-plugin</artifactId>
  <version>2.0-beta-9</version>
  <configuration>
    <useReleaseProfile>false</useReleaseProfile>
    <goals>deploy</goals>
    <arguments>-Papache-release</arguments>
  </configuration>
</plugin>

And the profile being used for releases is the following:

<profile>
  <id>apache-release</id>
  <build>
    <plugins>
      <!-- We want to sign the artifact, the POM, and all attached artifacts -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-gpg-plugin</artifactId>
        <configuration>
          <passphrase>${gpg.passphrase}</passphrase>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>sign</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <!-- We want to deploy the artifact to a staging location for perusal -->
      <plugin>
        <inherited>true</inherited>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-deploy-plugin</artifactId>
        <configuration>
          <updateReleaseInfo>true</updateReleaseInfo>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
        <executions>
          <execution>
            <id>attach-sources</id>
            <goals>
              <goal>jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
        <configuration>
          <encoding>${project.build.sourceEncoding}</encoding>
        </configuration>
        <executions>
          <execution>
            <id>attach-javadocs</id>
            <goals>
              <goal>jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</profile>

Verify you are using JDK 1.4.2

Maven 2.0.X and its plugins should be built with JDK 1.4.2.

>mvn --version
...
Maven version: 2.0.X
Java version: 1.4.2_18

Release Process for Part Of Maven

  1. Prepare your POMs for release:
    1. Make sure there are no snapshots in the POMs to be released.
    2. Check that your POMs will not lose content when they are rewritten during the release process.
      • Verify that all pom.xml files have an SCM definition.
      • mvn release:prepare -DdryRun=true
      • Diff the original file pom.xml with the one called pom.xml.tag to see if the license or any other info has been removed. This has been known to happen if the starting <project> tag is not on a single line. The only things that should be different between these files are the <version> and <scm> elements. Any other changes, you must backport yourself to the original pom.xml file and commit before proceeding with the release.
  2. Publish a snapshot:
    >mvn deploy
    ...
    [INFO] [deploy:deploy]
    [INFO] Retrieving previous build number from apache.snapshots.https
    ...
    

    If you experience an error during deployment like a HTTP 401 check your settings for the required server entries as outlined in the Prerequisites.

    Note: Be sure that the generated artifacts respect the Apache release rules: NOTICE and LICENSE files should be present in the META-INF directory within the jar. For -sources artifacts, be sure that your POM does not use the maven-source-plugin:2.0.3 which is broken. The recommended version at this time is 2.0.4.

    Note: You should verify the deployment under Maven Snapshot repository on Apache.

    https://repository.apache.org/content/repositories/snapshots/org/apache/maven/plugins/maven-XXX-plugin/Y.Z-SNAPSHOT/
    
  3. Prepare the release
    mvn release:clean
    mvn release:prepare
    

    Note: Preparing the release will create the new tag in SVN, automatically checking in on your behalf.

    Note: If you're located in Europe then release:prepare may fail with 'Unable to tag SCM' and 'svn: No such revision X'. Wait 10 seconds and run mvn release:prepare again.

  4. Stage the release for a vote
    mvn release:perform
    

    The release will automatically be inserted into a temporary staging repository for you. See the Nexus staging documentation for full details.

  5. Close the staging repository

    Login to https://repository.apache.org using your Apache SVN credentials. Click on "Staging". Then click on "org.apache.maven" in the list of repositories. In the panel below you should see an open repository that is linked to your username and ip. Right click on this repository and select "Close". This will close the repository from future deployments and make it available for others to view. If you are staging multiple releases together, skip this step until you have staged everything.

    See the image below for details.

    Closing the repository
  6. Verify the Staged artifacts

    If you click on your repository, a tree view will appear below. You can then browse the contents to ensure the artifacts are as you expect them. Pay particular attention to the existence of *.asc (signature) files. If the you don't like the content of the repository, right click your repository and choose "Drop". You can then rollback your release and repeat the process.

    Note the repository URL, you will need this in your vote email.

    Validating the artifacts
  7. Stage the latest documentation

    The plugin parent POM is configured to stage the documentation in a "versioned" directory such as /plugins/maven-XXX-plugin-Y.Z.

    1. Stage the documentation for the current release version (not the new snapshot).
      cd target/checkout
      mvn site:stage-deploy -Preporting
      

      Note: It requires Maven 2.1.0 or higher to successfully deploy to people.apache.org via SSH. Older Maven versions will fail due to com.jcraft.jsch.JSchException: Algorithm negotiation fail.

      Note: You should verify the deployment of the site on the Maven website (you need to wait the sync).

      http://maven.apache.org/plugins/maven-XXX-plugin-Y.Z/
      

      Some developers have reported problems with the site:stage-deploy goal. In that case, you can stage the site locally and upload it manually:

      mvn site:stage -Preporting
      scp -r target/staging/people.apache.org/www/maven.apache.org/plugins/maven-XXX-plugin YOUR_APACHE_USERNAME@people.apache.org:/www/maven.apache.org/plugins/maven-XXX-plugin-Y.Z
      
    2. Verify/change folder permissions to 0775 and files permissions to 0664. Log on to people.apache.org and change to the directory above the staging directory. That would be /www/maven.apache.org/plugins for a plugin. Then run these commands:
      find . -type d -exec chmod a+rx,g+w {} \;
      find . -type f -exec chmod 664 {} \;
      
  8. Propose a vote on the dev list with the closed issues, the issues left, the staging repository and the staging site. For instance:
    To: "Maven Developers List" <dev@maven.apache.org>
    Subject: [VOTE] Release Maven XXX plugin version Y.Z
    
    Hi,
    
    We solved N issues:
    http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=XXX&styleName=Html&version=XXX
    
    There are still a couple of issues left in JIRA:
    http://jira.codehaus.org/secure/IssueNavigator.jspa?reset=true&pid=XXX&status=1
    
    Staging repo:
    https://repository.apache.org/content/repositories/maven-staging-[YOUR REPOSITORY ID]/
    
    Staging site:
    http://maven.apache.org/plugins/maven-XXX-plugin-Y.Z/
    
    Guide to testing staged releases:
    http://maven.apache.org/guides/development/guide-testing-releases.html
    
    Vote open for 72 hours.
    
    [ ] +1
    [ ] +0
    [ ] -1
    
    

    To get the JIRA release notes link, browse to the plugin's JIRA page, select the Road Map link, and use the link to Release Notes that is next to the version being released.

    To get the list of issues left in JIRA, browse to the plugin's JIRA page, and from the Preset Filters on the right, use the link for Outstanding issues.

  9. Check the vote results

    Copied from Votes on Package Releases.

    Votes on whether a package is ready to be released follow a format similar to majority approval
    -- except that the decision is officially determined solely by whether at least three
    +1 votes were registered. Releases may not be vetoed. Generally the community will table the
    vote to release if anyone identifies serious problems, but in most cases the ultimate decision,
    once three or more positive votes have been garnered, lies with the individual serving as
    release manager. The specifics of the process may vary from project to project, but the
    'minimum of three +1 votes' rule is universal.
    

    The list of binding voters is available at http://people.apache.org/~jim/projects.html#maven-pmc

    Once a vote is successful, post the result to the dev list and cc the PMC. For instance:

    To: "Maven Developers List" <dev@maven.apache.org>
    CC: "Maven Project Management Committee List" <private@maven.apache.org>
    Subject: [RESULT] [VOTE] Release Maven XXX plugin version Y.Z
    
    Hi,
    The vote has passed with the following result :
    
    +1 (binding): <<list of names>>
    +1 (non binding): <<list of names>>
    
    I will promote the artifacts to the central repo.
    

    If the vote is unsuccessful, the process will need to be restarted. Be sure to drop your staging repository as described above.

  10. Promote the release

    Once the release is deemed fit for public consumption it can be transfered to a production repository where it will be available to all users.

    Login to https://repository.apache.org with your Apache SVN credentials. Click on "Staging" and then on the repository with id "maven-staging". Find your closed staging repository, right click on it and choose "Promote". Select the "Releases" repository and click "Promote".

    See image below.

    Promote the artifacts

    Next click on "Repositories", select the "Releases" repository and validate that your artifacts exist as you expect them.

  11. Deploy the current website

    Note: Be sure to generate and deploy the site using the same version of the release. Typically, you need to check out the tag (or go to target/checkout)

    cd target\checkout
    mvn site-deploy -Preporting
    

    Note: You can not just copy the documentation from Step 7 into the released documentation as the links are not identical. See the email thread http://www.nabble.com/forum/ViewPost.jtp?post=24018250&framed=y

  12. Review the website

    Wait for the files to arrive at

    http://maven.apache.org/plugins/maven-XXX-plugin
    

    or for a shared component at

    http://maven.apache.org/shared/maven-XXX
    

    The wait is necessary to allow the site to be rsync'ed into production.

  13. Update the maven site

    Check out the maven site project: https://svn.apache.org/repos/asf/maven/site/trunk

    If this is a plugin release, update the version number for the plugin on the src/site/apt/plugins/index.apt page.

    If this is a shared component release, update the version number for the component on the src/site/apt/shared/index.apt page.

    Commit your changes and then deploy the site.

    mvn site-deploy
    
  14. Update JIRA

    For a plugin, go to Admin section in JIRA for the maven-XXX-plugin project and mark the Y.Z version as released. Create version Y.Z+1, if that hasn't already been done.

    If this is a shared component, go to Admin section in JIRA for the MSHARED project and mark the maven-XXX-Y.Z version as released. Create version maven-XXX-Y.Z+1, if that hasn't already been done.

  15. Create an announcement. For instance:

    Note: You must send this email from your apache email account, e.g. YOUR_APACHE_USERNAME@apache.org otherwise the email to announce@maven.apache.org will bounce.

    From: YOUR_APACHE_USERNAME@apache.org
    To: announce@maven.apache.org, users@maven.apache.org
    Cc: dev@maven.apache.org
    Subject: [ANN] Maven XXX Plugin Y.Z Released
    
    The Maven team is pleased to announce the release of the Maven XXX Plugin, version Y.Z
    
    This plugin (insert short description of the plugin's purpose).
    
    http://maven.apache.org/plugins/maven-XXX-plugin/
    
    You should specify the version in your project's plugin configuration:
    
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-XXX-plugin</artifactId>
     <version>Y.Z</version>
    </plugin>
    
    Release Notes - Maven 2.x XXX Plugin - Version Y.Z
    
    (Copy Here Release Notes in Text Format from JIRA)
    
    Enjoy,
    
    -The Maven team
    
    
  16. Add the release to the next board report, in the private subversion area.

    This is a PMC activity. If you are not a PMC member then email the "Maven Developers List" <dev@maven.apache.org> with a request to update this file for your release.

    From: YOUR_APACHE_USERNAME@apache.org
    To: dev@maven.apache.org
    Subject: [PMC] Maven XXX Plugin Y.Z needs adding to board report
    
    The Maven XXX Plugin has been released.
    Can this get added to the next board report please.
    
  17. Add the release to the wiki, under the Recent Releases section of the front page and on the Releases page.

    Note: If you don't have access to edit this page email "Jason van Zyl" <jason@maven.org>

  18. Celebrate :o)

Trouble Shooting

mvn release:prepare "commit failed" during Prepare the release

If you get an error message similar to:

    [INFO] Unable to tag SCM
    Provider message:
    The svn tag command failed.
    Command output:
    svn: Commit failed (details follow):
    svn: File '/repos/asf/maven/plugins/tags/maven-eclipse-plugin-2.7/src/main/java/org/apache/maven/plugin/eclipse/EclipsePlugin.java' already exists

Then the resolution is to use a Subversion client 1.6+ and to run svn update.

mvn release:prepare "commit failed" during Prepare the release

If you get an error message similar to:

[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Unable to tag SCM
Provider message:
The svn tag command failed.
Command output:
svn: Path 'https://svn.apache.org/repos/asf/maven/plugins/tags/maven-eclipse-plugin-2.7' already exists

Then the resolution is to delete the tag using svn del -m "re-releasing build" <svn path>