Publishing Maven Repo in 5 Minutes

Publishing Maven Repo in 5 Minutes

Chances are you’re already using the Maven Central Repo, which is the default repo when you installed Maven. Today I’ll show you how to publish your artifacts to it.

Backgrounds

The Central Repository (http://search.maven.org/) is an index containing all publicly available Maven artifacts. Maven by default downloads all dependencies from the Central Repo . It does not host the files. Instead, you need to use one of the repo hosting services, and then publish your files to the Central Repo. I’ll demo the following services:

  • Sonatype OSSRH
  • JFrog Bintray

I recommend reading Comparing the Two to choose your preference first.

More Backgrounds on Sonatype

Sonatype’s repo system is a bit complex. I’ll try my best to make it simple (after reading the nexus book).

Sonatype Professional is a repo system. OSSRH is a free publicly available Sonatype Profressional.

The general steps of publishing artifacts are:

# Snapshot (not supported by Bintray)
Build artifacts -> Sign artifacts (optional) -> Snapshot Repo

# Release
Release artifacts -> Sign artifacts -> Staging Repo -> Release Repo

The life cycle of staging repo (notice the open and close states):

Prerequisites

  1. Install gpg
  2. Generate a key pair for signing your artifacts (instructions here)
  3. (For Sonatype) Go to https://issues.sonatype.org/secure/Signup!default.jspa and sign up an account, which will be used to upload artifacts.
  4. (For Sonatype) Register a group ID. To do this, create a Jira ticket like this.
  5. (For Bintray) Register a Bintray account.
  6. Make sure your’re familiar with Maven release plugin. You can read Maven release in 5min.

Warning
It usually takes a couple of days for Sonatype group ID to get approved.
Also, you may need to prove that you own a domain if your group ID is a domain name.
Please read the registration policy.

And start your timer now!

Source Code

You can fork the following project to use for this example (remember to change <groupId> in pom.xml).
https://github.com/ryan-ju/resteasy-demo-01

Using Sonatype OSSRH

Releasing Snapshot

  • Add Sonatype account and gpg keys to ~/.m2/settings.xml
  • Add SCM and repositories to project’s pom.xml
  • Configure gpg and nexus staging plugin to upload snapshots to Sonatype

Configure your .m2/settings.xml to add your Sonatype account and gpg keys.

<settings>
  <servers>
    <server>
      <id>ossrh-server</id>
      <username>your-jira-id</username>
      <password>your-jira-pwd</password>
    </server>
  </servers>
  <profiles>
    <profile>
      <id>ossrh</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <gpg.executable>gpg(the shell command)</gpg.executable>
        <gpg.passphrase>the_pass_phrase(for the secret key)</gpg.passphrase>
      </properties>
    </profile>
  </profiles>
</settings>

And then add scm and repos to your pom.xml.

<scm>
    <connection>scm:git:git@github.com:ryan-ju/resteasy-demo-01.git</connection>
    <developerConnection>scm:git:git@github.com:ryan-ju/resteasy-demo-01.git</developerConnection>
    <url>git@github.com:ryan-ju/resteasy-demo-01.git</url>
  <tag>HEAD</tag>
</scm>
<distributionManagement>
  <snapshotRepository>
    <id>ossrh-server</id>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
  </snapshotRepository>
  <repository>
    <id>ossrh-server</id>
    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
  </repository>
</distributionManagement>

Then configure the plugins. See comments for explanation.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>2.4</version>
            <executions>
                <execution>
                    <id>attach-sources</id>
                    <goals>
                        <goal>jar-no-fork</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>2.10.3</version>
            <executions>
                <execution>
                    <id>attach-javadocs</id>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-gpg-plugin</artifactId>
            <version>1.5</version>
            <!-- Automatically gets passphrase from property gpg.passphrase -->
            <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.6</version>
            <!-- This plugin is an extension to the deploy phase, adding a new deployment type -->
            <extensions>true</extensions>
            <configuration>
                <!-- The server ID configured in settings.xml  -->
                <serverId>ossrh-server</serverId>
                <nexusUrl>https://oss.sonatype.org/</nexusUrl>
                <!-- Not important for snapshots -->
                <autoReleaseAfterClose>false</autoReleaseAfterClose>
            </configuration>
        </plugin>
    </plugins>
</build>

nexus-staging-maven-plugin
The available goals include deploy, release and drop. For full list, see here.

Now you’re ready to stage the artifact. Run

mvn clean deploy

and you should see your snapshot artifacts in https://oss.sonatype.org/

Releasing Release

  • Build must satisfy the requirements
  • Prepare your release with release:prepare
  • Release with release:perform
  • (Optional) Execute mvn nexus-staging:release to upload artifacts to

First, you need to run

mvn release:prepare

Then run

mvn release:perform

which will upload the artifacts to a staging repo. This is because the perform goal by default runs a deploy phase, and the nexus plugin’s deploy goal is bound to deploy phase. To configure what phases are run by perform, set the <goals> configuration.

You can now release the artifacts with (reference)

mvn nexus-staging:release

Alternatively, you can do release with Maven release plugin(reference)

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-release-plugin</artifactId>
  <version>2.5.3</version>
  <configuration>
    <autoVersionSubmodules>true</autoVersionSubmodules>
    <useReleaseProfile>false</useReleaseProfile>
    <releaseProfiles>release</releaseProfiles>
    <!-- This will release the artifacts after staging them -->
    <goals>deploy nexus-staging:release</goals>
  </configuration>
</plugin>

and run

mvn release:prepare release:perform

Now you can find your artifacts in the Central Repo http://mvnrepository.com/.

Using JFrog Bintray

Staging Artifacts

  • Add Bintray account to .m2/settings.xml
  • Create a package to hold your artifacts
  • Add SCM and repositories to project’s pom.xml

First, add a server tag to your .m2/settings.xml.

<server>
  <id>bintray</id>
  <username>{bintray-user}</username>
  <password>{bintray-api-key}</password>
</server>

where the api key can be found in you Bintray profile

Then create a package in your Bintray’s Maven repo. This is a Bintray specific tag for organizing artifacts. In my case I created “resteasy-demo-01” package.

Now edit your pom.xml to include

  • The scm tag so the release plugin can update the versions
  • The remote repo
  • The necessary plugins
<scm>
    <connection>scm:git:git@github.com:ryan-ju/resteasy-demo-01.git</connection>
    <developerConnection>scm:git:git@github.com:ryan-ju/resteasy-demo-01.git</developerConnection>
    <url>git@github.com:ryan-ju/resteasy-demo-01.git</url>
    <tag>HEAD</tag>
</scm>
<distributionManagement>
    <repository>
        <id>bintray-repo-maven</id>
        <url>https://api.bintray.com/maven/ryan-ju/maven/resteasy-demo-01/</url>
    </repository>
</distributionManagement>
<!-- Dependencies go here -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <executions>
                <execution>
                    <id>attach-sources</id>
                    <goals>
                        <goal>jar-no-fork</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <executions>
                <execution>
                    <id>attach-javadocs</id>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-release-plugin</artifactId>
            <version>2.5.3</version>
            <configuration>
                <autoVersionSubmodules>true</autoVersionSubmodules>
            </configuration>
        </plugin>
    </plugins>
</build>

Then you can release your artifacts to Bintray

# This creates a tag for the release version in GitHub, and increment to the next SNAPSHOT version (e.g., 1.0.1-SNAPSHOT to 1.0.2-SNAPSHOT).
# This also generates a release.properties file in your work dir
# As long as release.properties exists, this command is idempotent.
mvn release:prepare

# This command releases artifacts to remote repo.  The actual files are from the release version, not the snapshot (obviously).
mvn release:perform

And you should see the artifacts under the package you created.

Up till now, the file aren’t publicly available. To publish them (to your repo, not Maven Central), click the button

Now you can use the repo in other projects by including the following in pom.xml

<repositories>
  <repository>
    <id>bintray</id>
    <url>http://dl.bintray.com/{bintray-user}/{bintray-repo}</url>
    <releases>
      <enabled>true</enabled>
    </releases>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
  </repository>
</repositories>

Warning
You should also configure the gpg key used to sign your artifacts. This can be done by clicking “Edit” in your Bintray profile and add a public key in the format

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

<key content>

-----END PGP PUBLIC KEY BLOCK-----

Releasing Artifacts

You need to click “Add to JCenter” button in your repo and give a group ID you want to publish under.

and then I guess you just need to wait for it to be approved.

Once that’s done, you should be able to find it in the Central Repo.

Comparing the Two

Both of the hosting services offer staging and publishing ability.

Bintray is easier to set up and can be used straight away (without requesting for a group ID), but can only host release versions of files (no SNAPSHOTs). The web UI is more intuitive and easier to use.

Sonatype is more complicated, but you can stage both snapshot and release versions of your artifacts. The web UI isn’t as pretty as Bintray, but still usable.

References

OSSRH Apache Maven configuration: http://central.sonatype.org/pages/apache-maven.html
Repository management with Nexus: https://books.sonatype.com/nexus-book/reference/staging-deployment.html
A practical guide to uploading to Maven central: http://knowm.org/a-practical-guide-to-uploading-artifacts-to-maven-central/
Nexus staging plugin: https://books.sonatype.com/nexus-book/reference/staging-deployment.html
Bintray tutorial: http://veithen.github.io/2013/05/26/github-bintray-maven-release-plugin.html

Written with StackEdit.

No comments:

Post a Comment