HerokuにPlay2アプリをpushする際にキャッシュをクリアする

こんにちは

最近GitHub上に自前のMaven-Repositoryを作成しました。

僕は普段の仕事では汎用のライブラリ(Java)を書く時間とWebアプリ(Play1 or Play2)を書く時間が半々くらいなんですが、これまではアプリから自前のライブラリを使用する場合は作成したjarファイルを直接アプリのlibフォルダにコピーしていました。

それがMaven-Repositoryをインターネット上に置くことによってアプリのライブラリ管理フレームワーク(Play1ではivy、Play2ではSBT)から直接取得することができるようになるわけです。

作成したアプリはたいていHerokuで動かしているんですが、Play2の場合はBuild.scalaにリポジトリの情報を設定することで自前のリポジトリからもライブラリを取得することができます。

残念ながらPlay1の場合はHerokuから自前のリポジトリを使うことはできません。Play1の枠組みではリポジトリの設定は「ivysetting.xml」で行うのですが、Herokuのbuildpackが内部でこのファイルを上書きしてしまうためです。(自分でカスタムbuildpackを作れば対応は可能なはずですが。)

 

★Play2で設定してみる

せっかくリポジトリを作成したので現在作成中のアプリでjarをリポジトリから取得するように修正してみます。

修正するファイルはBuild.scalaの1ファイルのみです。

 

import sbt._
import Keys._
import play.Project._

object ApplicationBuild extends Build {

  val appName         = "sqlsync"
  val appVersion      = "1.0-SNAPSHOT"

  val appDependencies = Seq(
    // Add your project dependencies here,
    jdbc,
    anorm,
    "postgresql" % "postgresql" % "9.1-901.jdbc4",
    "jp.co.flect" % "flectSalesforce" % "1.0-SNAPSHOT"
  )


  val main = play.Project(appName, appVersion, appDependencies).settings(
    // Add your own project settings here      
    resolvers += "FLECT Repository" at "http://shunjikonishi.github.io/maven-repo/"
  )
}

 

こんな感じ。

元々はlibフォルダにflectSalesforceとそれの依存するflectCommon, flectSoapの各jarを置いていたんですけど、それらをまるっと削除して起動してみます。

すると起動時にSBTによる依存性解決のログがずらずらと流れて無事に起動。ちゃんと動きます。

次いでHerokuにpushしてみると、Slugコンパイル時に依存性が解決されてこちらも無事に動作しました。

素晴らしい。

 

★ライブラリ開発中はこんな設定するもんじゃない

と、喜んではみたものの実は現在の開発はライブラリの開発が主でアプリは単純にそれにUIをかぶせているだけのものだったのでした。。。

つまり、これまでは日常的に以下のような操作を行っていました。

  1. エディタでライブラリのコードを修正
  2. Mavenでビルド
  3. Antで生成したjarファイルをアプリのlibフォルダにコピー
  4. アプリ再起動して動作確認

めんどくさい。(--
(ちなみにIDEの類は普段まったく使いません。)

これがリポジトリを使用するようになると以下のように手順が変わります。

  1. エディタでライブラリのコードを修正
  2. Mavenでビルド
  3. MavenでGitHubのリポジトリにデプロイ
  4. play cleanコマンド実行
  5. アプリ再起動して動作確認

「play clean」が必要なのはそうしないとSBTのキャッシュが効いて更新されたjarファイルがリポジトリから取得されないためです。

そもそも手順が増えてるし、GitHubへのデプロイはかなり時間がかかるし、キャッシュがなくなっているせいで起動時に毎回依存性の全解決が走るし、とまったく良いことがありません。。。(--

ていうか、コード1行修正しただけでもデプロイが必要とか明らかに間違ってますよね。

ライブラリの安定ビルドを使用するだけのアプリならリポジトリから持ってくれば良いですが、今回のようにライブラリ開発とアプリ開発がセットになっているケースでは、これまで通りjarを直接libにコピーする方式を取った方が良いように思います。

ここに至って初めてMavenがプロジェクト新規作成時に付加するバージョン番号「1.0-SNAPSHOT」の意図がちゃんとわかった気がします。(^^;;;

 

★HerokuのSBTキャッシュをクリアする

ところでこの話、まだ続きがあります。

ライブラリを何回か更新したところで、再びHerokuにpushしたんですがこれはコンパイルエラーになりました。

理由は追加したはずのメソッドが見つからないため。そう、Herokuのスラグコンパイル時にもSBTのキャッシュは有効なため新しいjarを持ってきてくれないんですよね。。。

今回の場合リポジトリを使う設定を外してlibコピー方式に変更すれば良いのですが、なんか方法があるだろうと思って探してみたところ見つけました。

http://stackoverflow.com/questions/15945263/heroku-play-framework-2-sbt-dependencies-cache

要約するとheroku configに「BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-scala.git#cleancache」を指定するだけ。そうすると次回ビルド時にはキャッシュクリアバージョンのbuildpackがスラグコンパイルしてくれるという寸法です。

実のところこの解決方法自体は予想通りのモノでした。探し始めた時点でbuildpackにキャッシュクリアする1行を足せばできるよなぁ、と思っていたので。

そんな中で今回の発見はこれ。

BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-scala.git#cleancache

buildpackは元々GitHubで公開されたものを直接持ってくるという大胆な仕組みで動いてますが、URLの末尾に「#xxxx」をつけるとmasterではなく指定のブランチを持ってくることができるのでした。

そう思ってみると、実はbuildpackのブランチには若干の機能違いと思われるブランチがいくつか並んでいたりもします。

いや~、知らなんだ。。。

残念ながらブランチの説明というのは(git的にも)ないので、どこが違うのかを見るためにはdiffを見るしかないですがGitHubのブランチはこういう使い方もアリなんですね。(^^;

コメント(0)