How To Publish Artifacts to the Maven Central Repository

I have just finished releasing my first project to Maven Central Repository and wanted to capture my notes for the setup of the project and all of the steps required.

Resources

Create account on OSSRH

You will need an account to the sonatype JIRA for OSSRH.  From there, you can request the creation of a new project. See http://central.sonatype.org/pages/ossrh-guide.html for details.

Setup of the Project/pom and Pre-requisites:

PGP keys

http://central.sonatype.org/pages/working-with-pgp-signatures.html

Create a set of PGP keys

gpg2 --gen-key

List the keys

gpg2 --list-keys
/usr/local2/home/rchapin/.gnupg/pubring.gpg
-------------------------------------------
pub   4096R/E5170CE8 2015-03-26 [expires: 2016-03-25]
uid                  Ryan Chapin <rchapin@nbinteractive.com>
sub   4096R/8DAF9AD6 2015-03-26 [expires: 2016-03-25]

The id for the key created is ‘E5170CE8’

Distribute the public key

gpg2 --keyserver hkp://pool.sks-keyservers.net --send-keys E5170CE8

Additions to be added to the pom

Add the <license> tag to your pom. Following are some links regarding available licenses and an example of it’s use in the pom.

I typically use the BSD 3 License, and added the following in the pom:

<project>
  ...
  <licenses>
    <license>
      <name>The BSD 3-Clause License</name>
      <url>http://opensource.org/licenses/BSD-3-Clause</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  ...
</project>

...

Add the <developers> tag to your pom and add a <developer> entry for yourself:

<project>
  ...
  <developers>
    <developer>
      <id>rchapin</id>
      <name>Ryan Chapin</name>
      <email>rchapin@nbinteractive.com</email>
      <url>http://www.ryanchapin.com</url>
      <roles>
        <role>architect</role>
        <role>developer</role>
      </roles>
      <timezone>America/New_York</timezone>
      <properties>
        <picUrl>http://www.gravatar.com/516f2158d74d134faa9649e9180ef782</picUrl>
      </properties>
    </developer>
  </developers>
  ...
</project>

 Add the <scm> tag to your pom with the details for your repository:

<project>
  ...
  <scm>
    <connection>scm:git:git@github.com:rchapin/hash-generator.git</connection>
    <developerConnection>scm:git:git@github.com:rchapin/hash-generator.git</developerConnection>
    <url>git@github.com:rchapin/hash-generator.git</url>
    <tag>HEAD</tag>
  </scm>
  ...
</project>

Distribution Management and Authentication:  Configure the pom to enable maven to deploy to OSSRH Nexus server with the Nexus Staging Maven plugin.  See below for the release profile configuration which will contain the configs for the nexus-staging-maven-plugin.

<project>
  ...
  <distributionManagement>
    <snapshotRepository>
    <id>ossrh</id>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    </snapshotRepository>
  </distributionManagement>
  ...
</project>

Create a profile to encapsulate the creation of the javadoc and source jar as well as the pgp signing of the artifacts.  In my case, I set the profile to <activeByDefault>true</activeByDefault> to ease release builds and simply invoke a build as such during development of the project to turn off the release profile

mvn package -P\!release

Also, configure the nexus-staging-maven-plugin setting <autoReleaseAfterClose>false</autoReleaseAfterClose> to enable manual inspection of the staging repository BEFORE it is released to central.  To deploy to OSSRH and release to the Central Repository in one step, set autoReleaseAfterClose to true.

<profiles>
    <profile>
      <id>release</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <build>
        <plugins>

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>${maven.javadoc.plugin.version}</version>
            <executions>
              <execution>
                <id>attach-javadocs</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>${maven.source.plugin.version}</version>
            <executions>
              <execution>
                <id>attach-sources</id>
                <goals>
                  <goal>jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-gpg-plugin</artifactId>
            <version>1.6</version>
            <executions>
              <execution>
              <id>sign-artifacts</id>
              <phase>verify</phase>
              <goals>
                <goal>sign</goal>
              </goals>
              </execution>
            </executions>
          </plugin>

          <plugin>
            <groupId>org.sonatype.plugins</groupId>
            <artifactId>nexus-staging-maven-plugin</artifactId>
            <version>1.6.5</version>
            <extensions>true</extensions>
            <configuration>
              <serverId>ossrh</serverId>
              <nexusUrl>https://oss.sonatype.org/</nexusUrl>
              <autoReleaseAfterClose>false</autoReleaseAfterClose>
            </configuration>
          </plugin>

        </plugins>
      </build>
    </profile>

</profiles>

Add the maven-release-plugin to the <build> section.  This should include disabling the ‘release’ profile that we added/describe above, and then specify the deploy goal together with the activation of the ‘release’ profile for the deploy goal.

<project>
  ...
  <build>
    ...
    <plugins>
      ...
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-release-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
          <autoVersionSubmodules>true</autoVersionSubmodules>
          <useReleaseProfile>false</useReleaseProfile>
          <releaseProfiles>release</releaseProfiles>
          <goals>deploy</goals>
        </configuration>
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>

Adding credentials for both the distributionManagement and the pgp signing need to be added to the ~/.m2/settings.xml. One entry for your OSSRH login, and another entry for your PGP signing passphrase

OSSRH Login

<setting>
  ...
  <servers>
    <server>
      <id>ossrh</id>
      <username>your-uid</username>
      <password>your-passwd</password>
    </server>
  </servers>
  ...
</settings>

PGP Signing Passphrase

<setting>
  ...
  <profiles>
    <profile>
      <id>ossrh</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <gpg.executable>gpg2</gpg.executable>
        <gpg.passphrase>your-passphrase</gpg.passphrase>
      </properties>
    </profile>
  </profiles>
  ...
</settings>

Performing a SNAPSHOT Deployment

As long as your current pom version still ends in ‘SNAPSHOT’ you can deploy a snapshot version to the OSSRH

mvn clean deploy

To use the SNAPSHOT version in a project, users will need to add the snapshot repo to their Nexus, settings.xml or pom.xml. 

<project>
  ...
  <repositories>
    <repository>
      <id>ossrh-snapshots</id>
      <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
    </repository>
  </repositories>
  ...
</project>

Release and Deployment

First make sure that all of the code is pushed to the remote repo and that everything is merged into your main branch.  Then make sure that you are ON the main branch on the local machine.

Prepare Release

To do a dry run and insure that pom will be bumped as expected and to check that everything is in order. This will NOT check-in or tag anyting in the scm repository.

mvn release:prepare -DdryRun=true

Check the output and then do the following before running the actual prepare command

mvn release:clean

Execute the release:prepare

mvn release:prepare

 If you encounter any errors

mvn release:prepare -Dresume=false

Alternatively, you can use

mvn release:clean release:prepare

See http://maven.apache.org/maven-release/maven-release-plugin/examples/prepare-release.html for details.

Once the release has been performed the scm repository should be updated with the new tag and the pom should be bumped to the next version for the next iteration of development.

Perform Release

Once the release has been prepared and a tag created and the scm repository has been update, you can deploy to OSSRH. The following will deploy to a staging repository.

mvn release:perform

Inspecting Staging Repo and Releasing to Central

Login to OSSRH via https://oss.sonatype.org/.  Uid and passwd are the same for issues.sonatype.org. See http://central.sonatype.org/pages/releasing-the-deployment.html for details

Releasing to Central

Once you have inspected the staging repo and are ready to release the deployment to Central do the following

cd target/checkout
mvn nexus-staging:release

If this is your first release to central for this project, don’t forget to go back to your project creation request ticket and add a comment that you have promoted your first release so that your promotion can be verified and your artifacts synced with Central.  This step only needs to be done the first time you promote to central with a new OSSRH project.

Leave a Reply