Sunday, October 7, 2012

Deploying to Maven Central

I've been working on developing a vCard parsing library, called ez-vcard, and have decided to upload it to the Maven Central repository. This is the main code repository that all projects configured with Maven use by default. By uploading to Maven Central, developers can more easily use your library with their own projects.

This blog post documents the steps I had to take to do this. Official instructions can be found here, which is where I got most of this information. It's a fairly complex process, so make sure you take your time and don't rush yourself! Your project is going to be released to the world, so make sure you do it right!

1. Prepare the POM file

First, you have to make sure that your POM file is ready.

a. The groupId of your project must be under a domain that you control. If your project is hosted by code hosting service like Sourceforge, then you can prefix the groupId with the hosting service's domain. For example:

  • Sourceforge: net.sf.projectName
  • Google Code: com.googlecode.projectName
  • Github: com.github.projectName

b. The POM must contain the following information:

  • <modelVersion>
  • <groupId>
  • <artifactId>
  • <version>
  • <packaging>
  • <name>
  • <description>
  • <url>
  • <licenses>
  • <scm><url>
  • <scm><connection>
  • <developers>

c. It also must reference the "oss-parent" parent POM if you want to use the special Maven goals to deploy your project (explained in step 4 below).

<parent>
  <groupId>org.sonatype.oss</groupId>
  <artifactId>oss-parent</artifactId>
  <version>7</version>
</parent>

d. Also note that usage of <repository>s and <pluginRepository>s inside of your POM is strongly discouraged. All of your project's dependencies should exist inside of Maven Central.

See the POM of the ez-vcard project for an example of a well-formed POM file.

2. Submit a Sonatype JIRA ticket

You will need to create an account on the Sonatype JIRA website and then submit a JIRA ticket so that your project can be reviewed. Someone will verify that your groupId is valid and that your POM has all the required information. It takes approximately 2 business days to process your request (my ticket was approved the same day I submitted it).

For instructions on how to create a JIRA account and fill out a JIRA ticket, see the Sonatype OSS Maven Repository Usage Guide.

3. Create a public key

While you're waiting for your ticket to be approved, you can generate a public key, which will be used to sign all files that you upload to Maven Central. File signatures are required in order to deploy to Maven Central. A file's signature is stored as a plain text file with the ".asc" extension. They are used to verify whether or not the file was uploaded by the real author.

The public key can be created using a tool called GPG. Most Linux distributions come with this tool pre-installed. If you're on a Windows or Mac computer, you'll have to download it separately (see this page for instructions).

Generate the key

A key can be generated using the following command:

> gpg --gen-key

The command will ask you for the following information (the supplied default is fine for many of these steps):

  1. Key type
  2. Key size - A high key size means the key will be harder to crack, but it will take longer to generate the key and longer to verify signed files. A size of 2048 is good.
  3. Expiration date - The key can be set to never expire, but for extra security, an expiration date can be set. If an expiration date is set, you'll have to regenerate your key once it has expired.
  4. Your name and email - This information will be used to label your public key in the public key database.
  5. A comment - This can be left blank. It is an optional component of the string that is created from your name and email.
  6. Key password - This is optional, but strongly recommended. You will need to enter this every time you sign a file (i.e. every time you deploy to Central).

Afterward, the tool will start collecting data from various activities that are going on inside your computer, such as keyboard and mouse activity. It uses this random data to build a random number called a seed. This seed will be used to kick start a random number generator, which is used to generate your key. It takes a little bit of time, so be patient. Open a text editor and start typing, or just do normal work on your computer. This will speed up the seed generation process.

Distribute the key

The next step is to upload your public key to the Internet. People can then download your key and use it to verify the signatures that you've uploaded with your project files.

First, get the name of your public key. You will need this to run the command that distributes the key. For example, in the console snippet below, the name of the public key is "ED69FC1F".

> gpg --list-keys
pub   2048R/ED69FC1F 2012-09-28
uid                  John Doe <jdoe@hotmail.com>
sub   2048R/E8A6EAD8 2012-09-28

Then, distribute your public key to the Internet with this command:

> gpg --keyserver hkp://pool.sks-keyservers.net/ --send-keys ED69FC1F

There are many key servers on the Internet, but the one above is what I think Maven Central requires or recommends that you to use.

For more information, see How To Generate PGP Signatures With Maven.

4. Deploy to Central

Once your JIRA ticket from step 2 has been approved, you can upload your project to a staging repository, where it will be released to Maven Central. Remember that, once you deploy a release to Central, that version of your library is set in stone. You cannot re-release your library unless you deploy a new version!!

Prepare the project

Before you start, make sure that you do the following:

a. Add your Sonatype JIRA credentials to your Maven settings file (located at "~/.m2/settings.xml").

<settings>
  ...
  <servers>
    <server>
      <id>sonatype-nexus-snapshots</id>
      <username>your-jira-id</username>
      <password>your-jira-pwd</password>
    </server>
    <server>
      <id>sonatype-nexus-staging</id>
      <username>your-jira-id</username>
      <password>your-jira-pwd</password>
    </server>
  </servers>
  ...
</settings>

b. Add "-SNAPSHOT" to the end of the version in the POM. Even though you are deploying a release version, the project's version in the POM file must end in "-SNAPSHOT". Maven will automatically remove this when it builds and deploys your project.

c. Commit all changes to source control. The working copy of your project must have zero uncommitted changes.

Build the project

Next, run these commands to get your project ready for uploading:

> mvn release:clean
> mvn release:prepare -Dusername=SCM_USERNAME -Dpassword=SCM_PASSWORD

The "release:prepare" goal asks you for the following:

  1. The release version of your project. For example, if the version in your POM is set to "0.4.1-SNAPSHOT", the release version should be "0.4.1".
  2. The name of the SVN tag to create. The goal will automatically create an SVN tag (or equivalent object if using a different SCM) for the release, which is why you need to provide your SCM credentials in the Maven command.
  3. The new version to assign to the project after it has been deployed. For example, if you are deploying "0.4.1", you might want the new development version to be "0.4.2-SNAPSHOT".

It then performs the following operations:

  1. Does a clean build of the project.
  2. Asks for your GPG key password to sign the built files.
  3. Changes the version and SCM URLs in your POM to reflect the release version, then commits these changes to your source control system.
  4. Creates a SVN tag (or equivalent) for the release version.
  5. Changes the version and SCM URLs in your POM to reflect the new development version that was entered above, then commits these changes to your source control system.

Upload the project

The next step is to upload your project to a staging repository. The staging repository gives you one last chance to confirm that your project is in good shape and ready to be released to the world. It also performs automated checks on your project to make sure it meets all the requirements.

> mvn release:perform

This command will:

  1. Checkout the SVN tag (or equivalent) that was created with the "release:prepare" goal.
  2. Build the checked-out files.
  3. Ask for your GPG key password to sign the built files.
  4. Upload everything to a staging repository (not Maven Central yet).

Release

Now that your project is in the staging repository, you can release it to the world!

  1. Open the Nexus UI by visiting https://oss.sonatype.org/. Login with the JIRA credentials you created in step 2.
  2. Click on "Staging Repositories" in the menu on the left.
  3. Find the staging repository for your project. Select it, then click the "Close" button. You will be asked to enter a comment describing your action. You can enter something like "Release of version 0.4.1". Closing the repository will perform some automated checks on your project. It makes sure that all files are signed, that your POM has all the required information, and that your project has source code and Javadoc JARs.
  4. If there is a problem with your project, you can click "Drop" to delete the staging repository so you can correct the mistakes, re-build, and re-stage your project.
  5. Once you've confirmed that your project is in good shape, click "Release". If the "Release" button is disabled, it means it is still performing some automated checks on your project. Wait a few seconds, then click the "Refresh" button. The "Release" should become enabled (if it is not, wait a few more seconds, then click "Refresh" again). After clicking "Release", you'll be asked again to enter a comment.
  6. Since this is the first time you are deploying your project to Central, your project must be manually reviewed to make sure everything is OK. Add a comment to the JIRA ticket that you created in step 2, saying that you have released the project. If everything is OK, then the Maven folks will configure your project to sync with Maven Central. It will appear there within 2 hours. All subsequent versions you release will be automatically synced with Central and this last step will not be necessary. It will take approximately 4 hours to appear on search.maven.org.

Congratulations! Your project is now part of the Maven community!

For more information, see the Sonatype OSS Maven Repository Usage Guide.