Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: gen-master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 192 lines (135 sloc) 9.905 kb
layout title
content
Deploying to Sonatype

Deploying to sonatype is easy! Just follow these simple steps:

First - PGP Signatures

You'll need to PGP sign your artifacts for the Sonatype repository. Don't worry, there's a plugin for that. Follow the instructions for the plugin and you'll have PGP signed artifacts in no time.

Note: The plugin is a jvm-only solution to generate PGP keys and sign artifacts. It can work with the GPG command line tool, but the command line is not needed.

Second - Maven Publishing Settings

To publish to a maven repository, you'll need to configure a few settings so that the correct metadata is generated.

publishMavenStyle := true

is used to ensure POMs are generated and pushed. Next, you have to set up the repositories you wish to push too. Luckily, Sonatype's OSSRH uses the same URLs for everyone:

publishTo <<= version { (v: String) =>
  val nexus = "https://oss.sonatype.org/"
  if (v.trim.endsWith("SNAPSHOT")) 
    Some("snapshots" at nexus + "content/repositories/snapshots") 
  else
    Some("releases"  at nexus + "service/local/staging/deploy/maven2")
}

Another good idea is to not publish your test artifacts:

publishArtifact in Test := false

Third - POM Metadata

Now, we want to control what's available in the pom.xml file. This file describes our project in the maven repository and is used by indexing services for search and discover. This means it's important that pom.xml should have all information we wish to advertise as well as required info!

First, let's make sure no repositories show up in the POM file. To publish on maven-central, all required artifacts must also be hosted on maven central. However, sometimes we have optional dependencies for special features. If that's the case, let's remove the repositories for optional dependencies in our artifact:

pomIncludeRepository := { _ => false }

Next, the POM metadata that isn't generated by SBT must be added. This is done through the pomExtra configuration option:

pomExtra := (
  <url>http://jsuereth.com/scala-arm</url>
  <licenses>
    <license>
      <name>BSD-style</name>
      <url>http://www.opensource.org/licenses/bsd-license.php</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  <scm>
    <url>git@github.com:jsuereth/scala-arm.git</url>
    <connection>scm:git:git@github.com:jsuereth/scala-arm.git</connection>
  </scm>
  <developers>
    <developer>
      <id>jsuereth</id>
      <name>Josh Suereth</name>
      <url>http://jsuereth.com</url>
    </developer>
  </developers>)

Specifically, the url, license, scm.url, scm.connection and developer sections are required. The above is an example from the scala-arm project.

Note that sbt will automatically inject licenses and url nodes if they are already present in your build file. Thus an alternative to the above pomExtra is to include the following entries:

licenses := Seq("BSD-style" -> url("http://www.opensource.org/licenses/bsd-license.php"))

homepage := Some(url("http://jsuereth.com/scala-arm"))

This might be advantageous if those keys are used also by other plugins (e.g. ls). You cannot use both the sbt licenses key and the licenses section in pomExtra at the same time, as this will produce duplicate entries in the final POM file, leading to a rejection in Sonatype's staging process.

The full format of a pom.xml file is outlined here.

Fourth - Adding credentials

The credentials for your Sonatype OSSRH account need to be added somewhere. Common convention is a ~/.sbt/sonatype.sbt file with the following:

credentials += Credentials("Sonatype Nexus Repository Manager", 
                           "oss.sonatype.org", 
                           "<your username>",
                           "<your password>")

Note: The first two strings must be "Sonatype Nexus Repository Manager" and "oss.sonatype.org" for Ivy to use the credentials.

Finally - Publish

In SBT, run publish and you should see something like the following:

> publish
Please enter your PGP passphrase> ***********
[info] Packaging /home/josh/projects/typesafe/scala-arm/target/scala-2.9.1/scala-arm_2.9.1-1.2.jar ...
[info] Wrote /home/josh/projects/typesafe/scala-arm/target/scala-2.9.1/scala-arm_2.9.1-1.2.pom
[info] Packaging /home/josh/projects/typesafe/scala-arm/target/scala-2.9.1/scala-arm_2.9.1-1.2-javadoc.jar ...
[info] Packaging /home/josh/projects/typesafe/scala-arm/target/scala-2.9.1/scala-arm_2.9.1-1.2-sources.jar ...
[info] :: delivering :: com.jsuereth#scala-arm_2.9.1;1.2 :: 1.2 :: release :: Mon Jan 23 13:16:57 EST 2012
[info] Done packaging.
[info] Done packaging.
[info] Done packaging.
[info]  delivering ivy file to /home/josh/projects/typesafe/scala-arm/target/scala-2.9.1/ivy-1.2.xml
[info]  published scala-arm_2.9.1 to https://oss.sonatype.org/service/local/staging/deploy/maven2/com/jsuereth/scala-arm_2.9.1/1.2/scala-arm_2.9.1-1.2-sources.jar
[info]  published scala-arm_2.9.1 to https://oss.sonatype.org/service/local/staging/deploy/maven2/com/jsuereth/scala-arm_2.9.1/1.2/scala-arm_2.9.1-1.2-javadoc.jar.asc
[info]  published scala-arm_2.9.1 to https://oss.sonatype.org/service/local/staging/deploy/maven2/com/jsuereth/scala-arm_2.9.1/1.2/scala-arm_2.9.1-1.2-sources.jar.asc
[info]  published scala-arm_2.9.1 to https://oss.sonatype.org/service/local/staging/deploy/maven2/com/jsuereth/scala-arm_2.9.1/1.2/scala-arm_2.9.1-1.2.jar
[info]  published scala-arm_2.9.1 to https://oss.sonatype.org/service/local/staging/deploy/maven2/com/jsuereth/scala-arm_2.9.1/1.2/scala-arm_2.9.1-1.2.jar.asc
[info]  published scala-arm_2.9.1 to https://oss.sonatype.org/service/local/staging/deploy/maven2/com/jsuereth/scala-arm_2.9.1/1.2/scala-arm_2.9.1-1.2.pom.asc
[info]  published scala-arm_2.9.1 to https://oss.sonatype.org/service/local/staging/deploy/maven2/com/jsuereth/scala-arm_2.9.1/1.2/scala-arm_2.9.1-1.2.pom
[info]  published scala-arm_2.9.1 to https://oss.sonatype.org/service/local/staging/deploy/maven2/com/jsuereth/scala-arm_2.9.1/1.2/scala-arm_2.9.1-1.2-javadoc.jar
[success] Total time: 9 s, completed Jan 23, 2012 1:17:03 PM

After publishing you have to follow the Release workflow of nexus. In the future, we hope to provide a Nexus SBT plugin that allows the release workflow procedures to be performed directly from SBT.

Note: Staged releases allow testing across large projects of independent releases before pushing the full project.

Note: An error message of PGPException: checksum mismatch at 0 of 20 indicates that you got the passphrase wrong. We have found at least on OS X that there may be issues with characters outside the 7-bit ASCII range (e.g. Umlauts). If you are absolutely sure that you typed the right phrase and the error doesn't disappear, try changing the passphrase.

Summary

To get your project hosted on Sonatype (and Maven Central), you will need to:

  • Have GPG key pair, with published public key,
  • A SBT file with your Sonatype credentials that is not pushed to the VCS,
  • Modify project/plugins.sbt to include the xsbt-gpg-plugin to sign the artefacts,
  • Modify build.sbt with the required elements in the generated POM.

Starting with a project that is not being published, you'll need to install GPG, generate and publish your key. Swtiching to SBT, you'll then need to:

~/.sbt/sonatype.sbt

This file (kept outside the VCS) contains the Sonatype credentials settings:

credentials += Credentials("Sonatype Nexus Repository Manager",
                           "oss.sonatype.org",
                           "your-sonatype-username",
                           "your-sonatype-password")

project/plugins.sbt

This file specifies the plugins for your project. If you intend to sign the artefacts, you'll need to include @jsuereth's xsbt-gpg-plugin:

resolvers += Resolver.url("sbt-plugin-releases", /* no new line */
  new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases")) /* no new line */
  (Resolver.ivyStylePatterns)

addSbtPlugin("com.jsuereth" % "xsbt-gpg-plugin" % "0.5")

build.sbt

Finally, you'll need to tweak the generated POM in your build.sbt. The tweaks include specifying the project's authors, URL, SCM and many others:

publishTo <<= version { v: String =>
  val nexus = "https://oss.sonatype.org/"
  if (v.trim.endsWith("SNAPSHOT")) Some("snapshots" at nexus + "content/repositories/snapshots")
  else                             Some("releases" at nexus + "service/local/staging/deploy/maven2")
}

publishMavenStyle := true

publishArtifact in Test := false

pomIncludeRepository := { _ => false }

pomExtra := (
  <url>http://your.project.url</url>
  <licenses>
    <license>
      <name>BSD-style</name>
      <url>http://www.opensource.org/licenses/bsd-license.php</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  <scm>
    <url>git@github.com:your-account/your-project.git</url>
    <connection>scm:git:git@github.com:your-account/your-project.git</connection>
  </scm>
  <developers>
    <developer>
      <id>you</id>
      <name>Your Name</name>
      <url>http://your.url</url>
    </developer>
  </developers>
)
Something went wrong with that request. Please try again.