k4200’s notes and thoughts

Programmer side of k4200

sbtプロジェクトをデプロイ(sbt 0.11)

rpscala 第100回でやった事。

やりたい事

sbtで出来たプロジェクトがあって、以下のものをリモート環境にデプロイしたい。

  • 自分で書いたコード
  • 依存ライブラリ

プロジェクト構成はこんな感じ。multi project構成になっている。モデル等共通部分のcommon、フロントエンドのwebsite、バックエンドのbgtasksの3つのプロジェクトで、前者2つはPlayProject、bgtasksは通常のsbt Project。なぜこんな構成になったかは、このスライドの6ページ辺りを参照。

環境

  • Play 2.0.4
  • Scala 2.9.1
  • sbt 0.11.3

試したもの

以下の3つを試した(or 試そうとした)。

sbt-assembly

最初に試したのは @tototoshi さんから教えてもらった sbt-assemly。基本的にはドキュメント通りなんだけど、plugins.sbt に以下のように書いても、jarが無いって言われた。

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.8.1")

これは以下のようにして回避。これに関してはSBT Masterのxuweiさんのブログを参照。

libraryDependencies += Defaults.sbtPluginExtra("com.eed3si9n" %% "sbt-assembly" % "0.7.2", "0.11.2", "2.9.1")

このプラグインは、fat jarを作ってくれるものなんだけど、作成にかなり時間がかかるので、まだ開発途中でこまめにビルドしたい場合に向かない。ということで採用は見合わせ。

sbt-pack と sbt-start-script

これらのプラグインは、依存しているjarを1箇所に集めて起動スクリプトも作ってくれる、とかそんな感じ。sbt 0.12以降じゃないとダメっぽいので諦めた。

追記:

xuweiさんからコメントを頂きました。sbt-start-scriptは「直接ivyのcacheディレクトリのjarを参照して起動するスクリプト生成」だそうです。いずれにしても、本番環境へのデプロイには向かないため見合わせ。

また、sbt0.11系のものも古いversionならあるとのこと。

http://typesafe.artifactoryonline.com/typesafe/releases/com.typesafe.startscript/xsbt-start-script-plugin/scala_2.9.1/sbt_0.11.3/
https://github.com/sbt/sbt-start-script/tree/v0.5.2

追記ここまで

やったこと

retrieveManaged := true

ProjectのsettingsにretrieveManaged := trueと書くと、lib_managedの下に依存しているjarファイルを取ってきてくれる。以下の様な感じ。

    val bgtasks = Project(
      appName + "-bgtasks", file("modules/bgtasks")
    ).settings(
      retrieveManaged := true, // ← これ
      libraryDependencies ++= appDependenciesBgtasks,
      resolvers ++= Seq(
        "Apache HBase" at "https://repository.apache.org/content/repositories/releases",
        "Rawson repo for Thrift" at "http://people.apache.org/~rawson/repo")
    ).dependsOn(common, common % "test->test")

ただ、lib_managed の下に、パッケージ名とかのディレクトリが作られて階層が深いので、デプロイする時にはシェルスクリプトでそれをどっか別の場所にまとめた。

find lib_managed -name '*.jar' | xargs -I {} cp {} /dest/dir
デプロイ

勉強してsbt-pluginとか書こうかなとちょっと思ったけど、そこまでする必要もないかと思って、シェルスクリプト内でscpで実行することにした。

実行

これはシェルスクリプトで。

#!/bin/bash
classpath=$(find lib_managed -name '*.jar' | tr '\n' ':')
classpath=${classpath}foo-bgtasks_2.9.1-1.0-SNAPSHOT.jar:foo-common_2.9.1-1.0-SNAPSHOT.jar
scala -cp $classpath package.name.Main

まとめ

分かっちゃえばそんな面倒でも無かった。でも、もう少し楽な方法があったら教えて下さい。