As I'm a massive
CloudBees fan, I'm starting to use more and more of their offerings. I've got a number of Play! Framework 2.1 apps (Scala flavour, natch) hosted up there and they
Just Work, but I wanted to write a Scala library on Github and push it up to a CloudBees-hosted Maven repo for general consumption.
SBT is a nice tool for developing Scala, and will happily publish to a Nexus or other such Maven/Ivy repository, but CloudBees is a little trickier than that, because it's best suited to hosting CloudBees-built stuff (i.e. the output of their Jenkins-In-The-Cloud builds).
Their support for uploading "external" dependencies is limited to the WebDAV protocol only - a protocol that SBT doesn't natively speak. Luckily, some excellent person has minimised the yak-shaving required by writing a
WebDAV SBT plugin - here's how I got it working for my build:
In
project/plugins.sbt, add the WebDAV plugin:
resolvers += "DiversIT repo" at "http://repository-diversit.forge.cloudbees.com/release"
addSbtPlugin("eu.diversit.sbt.plugin" % "webdav4sbt" % "1.3")
To avoid plastering your CloudBees credentials all over Github, create a file in
~/.ivy2/.credentials:
realm={account} repository
host=repository-{account}.forge.cloudbees.com
user={account}
password=
Where
{account} is the value you see in the drop-down at the top right when you login to
CloudBees Grand Central. Don't forget the Realm, this is just as important as the username/password!
Next, add this to the top of your
build.sbt:
import eu.diversit.sbt.plugin.WebDavPlugin._
and this later on:
credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")
seq(WebDav.globalSettings : _*)
publishTo := Some("Cloudbees releases" at "https://repository-{account}.forge.cloudbees.com/"+ "release")
What this does: The first line tells SBT where to find that credentials file we just added.
The second line makes the
webdav:publish task
replace the default
publish task, which is most-likely what you want. If it's not, use
WebDav.scopedSettings and invoke the task with
webdav:publish.
The third line specifies where to publish to, replacing all other targets. I found if I used the notation in the WebDAV plugin documentation:
publishTo <<= version { v: String =>
val cloudbees = "https://repository-diversit.forge.cloudbees.com/"
if (v.trim.endsWith("SNAPSHOT"))
Some("snapshots" at cloudbees + "snapshot")
else
Some("releases" at cloudbees + "release")
}
...SBT would attempt to upload my artifact to not-just CloudBees, but any other extra repository I had configured with the
resolvers expression higher up in
build.sbt, and hence try and upload to
oss.sonatype.org, which I'm not ready for just yet! "Releases" is sufficient for me, I don't need the "snapshots" option.
And with that, it should just work like a charm:
> publish
[info] WebDav: Check whether (new) collection need to be created.
[info] WebDav: Found credentials for host: repository-{account}.forge.cloudbees.com
[info] WebDav: Creating collection 'https://repository-{account}.forge.cloudbees.com/release/net'
[info] WebDav: Creating collection 'https://repository-{account}.forge.cloudbees.com/release/net/foo'
[info] WebDav: Creating collection 'https://repository-{account}.forge.cloudbees.com/release/net/foo/bar_2.9.2'
[info] WebDav: Creating collection 'https://repository-{account}.forge.cloudbees.com/release/net/foo/bar_2.9.2/0.1'
[info] WebDav: Done.
...
[info] published bar_2.9.2 to https://repository-{account}.forge.cloudbees.com/release/net/foo/bar_2.9.2/0.1/bar_2.9.2-0.1.pom
[info] published bar_2.9.2 to https://repository-{account}.forge.cloudbees.com/release/net/foo/bar_2.9.2/0.1/bar_2.9.2-0.1.jar
[info] published bar_2.9.2 to https://repository-{account}.forge.cloudbees.com/release/net/foo/bar_2.9.2/0.1/bar_2.9.2-0.1-sources.jar
[info] published bar_2.9.2 to https://repository-{account}.forge.cloudbees.com/release/net/foo/bar_2.9.2/0.1/bar_2.9.2-0.1-javadoc.jar