個人/社内 Maven Repository を作る

オープンソースScala ライブラリは sonatype を経由して Maven Central にデプロイするのが定番となっています。Maven Central のアカウントを持っていない、とかクローズドにしておきたい、などの理由から自前で Maven リポジトリを持ちたくなることがあるでしょう。

Maven リポジトリはなんとなくセットアップが面倒そうに思われていそうですが、実際には Web サーバ上にルールに従ってファイルが配置されているだけです。ArtifactoryNexus などの管理ツールもありますが、それらをインストールしなくとも簡単にセットアップが可能です。

例えば、gh-pages をリポジトリにしている人はたまに見かけます。自分も Sonatype のアカウントを作る前はそうしていました。それから svn リポジトリに jar を突っ込み、それを web 上に公開している人もいます。そういう風にリポジトリを公開するには、まず自分のローカルに Maven リポジトリを作り、それをアップロードする、という手順を踏みます。

自分のローカルにリポジトリを作るのがめんどうな場合は、WebDAV や scp を利用して、直接 Web 上のリポジトリにライブラリをデプロイすることも可能です。今回は WebDAV を使うことにしました。

まずは Web サーバの設定です。これは簡単で、WebDAV を有効にするだけです。Apache であれば次のような設定となります。 http://mvnrepoリポジトリの URL です。

<VirtualHost *:80>
  Servername mvnrepo
  DocumentRoot /var/www/mvnrepo
  DavLockDB /var/lock/apache2/DavLock
  DAVMinTimeout 600
  <Location />
    DAV On
  </Location>
</VirtualHost>

リポジトリができたら、リリース用のディレクトリとスナップショット用のディレクトリを切りましょう。 例えば、リリース用のディレクトリは http://mvnrepo/releases, スナップショット用のディレクトリは http://mvnrepo/snapshots という風にします。

次に、build.sbt に設定を追加します。

// Maven スタイルでデプロイする
publishMavenStyle := true

// テストは含めない
publishArtifact in Test := false

// 他のリポジトリのライブラリに依存することを許容する設定
pomIncludeRepository := { _ => false }

// リポジトリの設定
// SNAPSHOT バージョンであれば、http://mvnrepo/snapshots に
// リリースバージョンであれば、http://mvnrepo/releases にデプロイする
publishTo := {
  val inhouse = "http://mvnrepo/"
  if (version.value.trim.endsWith("SNAPSHOT"))
    Some("inhouse snapshots" at inhouse + "snapshots")
  else
    Some("inhouse releases"  at inhouse + "releases")
}

他に pomExtra の設定などもありますが、Maven Central ではないのでなくてもデプロイできるので割愛します。

さて、これであとは publish コマンドを打つだけですが、一つ問題があります。 sbt の問題か、sbt が依存するライブラリの問題かはわかりませんが、デプロイをするとき、パスの途中のディレクトリを作ってくれないのです。たとえば com.example という group_id で hello というライブラリの scala 2.11.x 用のバージョン 0.1.0 をデプロイしようとすると、その配置ディレクトリは /releases/com/example/hello_2.11/0.1.0/ ですが、このディレクトリを作る処理をせず、いきなりファイルを配置しようとするため、エラーが発生してしまいます。

これを避けるためには、自分で WebDAV の MKCOL リクエストを送る必要があります。もしくは Apache ではなく nginx を使って、create_full_put_path の設定を on にします。

今回は諸事情により、Apache を使うことになったので、自前で MKCOL を打つことになりますが、そんなことはやってられないので、解決策を探したところ、webdav4sbt という sbt プラグインを見つけました。このプラグインをインストールすると、sbt が publish の前に MKCOL リクエストを送ってくれるようになります。

しかし残念ながらこのライブラリはメンテナンスされておらず、ダウンロードもできない状態だったので Fork しました。scala 2.11 対応させ、名前も sbt-automkcol という風に変えました。

https://github.com/tototoshi/sbt-automkcol

注: 以下、情報が古くなっているのでGitHubのREADMEを参照してください

project/plugins.sbt に

addSbtPlugin("com.github.tototoshi" % "sbt-automkcol" % "1.5.1")

build.sbt に

import com.github.tototoshi.sbt.automkcol.Plugin._

AutoMkcol.globalSettings

と設定してください。

Apache の認証情報は ~/.sbt/0.13/build.sbt に書きます。

credentials += Credentials("inhouse maven repository", "mvnrepo", "user", "password")

これで Apache の場合でもデプロイができるようになります。

Maven リポジトリのセットアップ方法を紹介しましたが、オープンソースのライブラリであれば sonatype のアカウントを手にいれるなどして、Maven Central へデプロイすることを強くお勧めします。野良リポジトリの多くはいつのまにか管理されなくなり、ライブラリがダウンロードできなくなっているというのをよく見かけるからです。今回 Fork した webdav4sbt もリポジトリがなくなっていました。その点 Maven Central にデプロイすれば削除できないのでライブラリが消えることもありませんし、sbt に resolver の設定を追加する必要もありません。