Scalaで書いたWeb APIのライブラリとWerckerを連携させてみた(一時的に)
Werckerについては werckerでrspecとcucumberのCI環境を作る - zephiransasのチラシの裏 を参考にどんなものか掴んでもらうと良いかと思います。GithubやBitBucketのリポジトリと連携してCI環境を提供してくれるサービスです。
今回は、私が作っている Shinsuke-Abe/dropbox4s · GitHub をWerckerと連携させて、テストを実行させてみたので、そのメモです。なお、今は後述する理由によりいったん連携を削除しています。
ちなみに、他のライブラリでもCI環境が構築できないかと検討はしていたのですが、主に以下の点でベストな解が思い浮かばなかったので手を付けていませんでした。
この辺りについても一応の解が見えたので、メモを残しておきます。
トークンの問題
dropbox4sはDropbox API*1をScalaから使うものであるため、テスト時にユーザごとのトークンを必要とします。私のローカルにある開発環境でテストを流すときは、私のアカウントでトークンを発行して流せば良いのですが、さすがにこれをGithubにプッシュする訳にはいきません。
そこで、.gitignoreにプロパティファイルを追加して、トークンやその他個別にローカルで設定すべきものをプロパティファイルからロードするようにしていました。
これを今まで通り見せてはいけない設定についてはプッシュせずに個別にロードするために、環境変数を使うことにしました。
IDEの実行で環境変数を指定した設定をプロジェクトごとに作っていくというのも面倒だし、私の性格からして実行設定を間違えそうだったので、プロパティファイルが存在していればそちらを優先で、なければ環境変数を利用するという形に変更しています。キー名をプロパティとあわせているので、環境変数の命名からすると違和感を感じることにはなっていますがその辺りは気にしない方向で。
また、環境変数は内容を公開しない設定にできるので、トークンを見られることもなさそうです。
対応言語の問題
最近はどのサービスでもそんなことはないのですが、以前調べたときはまだScalaでのビルド環境はあまり公式ではアナウンスされておらずJavaの環境をちょっとこねくり回して、という状況だったように思います。というわけで、ビルド環境については今はさほど困らなくなったと思います。今回Werckerを選んでみたのは、数日前に会社でJavaのプロダクト向けに設定を書いてみたので、その復習がてらという理由にすぎません。
Werckerは公式でのScala対応はしていないのですが、実行環境などをまとめたBOXという概念があり、自分で作ったBOXをGithubやBitBucket経由で公開できるという特徴があります。サードパーティ製のBOXにTypesafe ActivatorをインストールしたBOXがあったので使ってみる事にしました。Typesafe Activatorとか使った事なかったんですが、中で動いているのはsbtっぽいですし、サブコマンドも結局sbtみたいなので問題ないかと。
ディレクトリが作られない
dropbox4sではダウンロードのテストのために一時的なローカルなディレクトリを必要とします。はじめは以下のようにwercker.ymlを書いていました。
box: amutake/activator@0.0.2 steps: - wercker/mktemp@1.0.0 # Build definition build: # The steps that will be executed on build steps: - script: name: make work directory code: | if [ ! -e ${downloadRoot} ]; then mkdir ${downloadRoot} fi - script: name: run test code: | activator test
これでビルドを流すと、mkdirのところでプロンプトが出てビルドが待ちになってしまいました。いつまでたっても変化なし。仕方がないのでビルドを終了させてSTEPを探して対応。
ifがダメなのか、ネストしているのがダメなのかは確認していません(Werckerでできることを探るよりもビルド流してみることが目的でしたし)。今回、ドキュメントをちゃんと読み切ってからやっていた訳ではないので、もしかしたらドキュメントに書いてあるかもしれません。
・・・フックされない?
前提としてmasterブランチにwercker.ymlが存在せず、別ブランチにのみwercker.ymlがある場合だと思っているのですが、別ブランチへのプッシュを拾ってくれなくて難儀しました。
いろいろと試してみた結果、以下の挙動のときには別ブランチでのビルドが走り始めました。
- masterに対して最初にビルドをかけたとき
- プルリクを作ろうとしたとき
masterにビルドをかけたときは、masterブランチには当然wercker.ymlがないのでテストもビルドも実行されずにパスしたのですが、その直後に別ブランチの最新のコミットに対してビルドが走りました。
その後、しばらくプッシュに対してはちゃんとフックしてくれない状況が続き。。。試しに別ブランチからのプルリクを作ろうとしたときに最新のコミットでビルドが走り始めるという感じ。
ドキュメントをちゃんと読めば解決する話なのではないかと思っていますが。
テストが通らない
ローカル環境では(たまに不安定になるものの)通るテストがこけるようになりました。リクエストを投げるタイミングだと踏んでいますが、細かい原因はわかっていません(ローカルではこけないので)。通っている他のテストと見比べてみても、環境依存するような箇所が見当たらないので途方に暮れている次第です。
ですが、環境変数の取得はうまく行っているようですし、Dropbox側がエラーで返している(つまりAPI自体はちゃんと実行している)状態なので、ビルド環境の構築としては問題ないということで。
wercker.yml
最終的にテストを流すことまでできた状態のwercker.ymlは以下のようになりました。
box: amutake/activator@0.0.2 steps: - wercker/mktemp@1.0.0 # Build definition build: # The steps that will be executed on build steps: - mktemp: envvar: downloadRoot directory: true - script: name: run test code: | activator test
テストについては確認すべき事はありますが、実行環境依存の設定などはちゃんと環境変数からとれているようなので(通っている部分のテストはそれがないと実行不可能)、基本的にはこの環境で問題ないはずです。
ただし、テストの問題については、まだまだ面倒そうな事が残っているため、動かした事に満足して今は連携をしないようにしてあります。
今後の課題
仕事で設定したときから思っていましたが、Githubへのpushを拾ってくれてビルドを流してくれるのはとても便利です。思っている使い方ができることもわかりましたし、とりあえず、以下を解決すれば運用は問題なさそうです。
- テストのやり方
- sbtの依存関係のあるライブラリをキャッシュする(主にビルド時間対策)
テストについては、落ちている部分はDropboxが公式に提供しているJavaのCoreAPIライブラリのラッパ部分なので、どうしても不安定ならモックを使うとかを考えています。もしくはテストのシナリオを抜本的に見直すか。
キャッシュについては、毎回依存ライブラリのダウンロードが走るとそれだけビルド時間を圧迫します。1ビルドの制約が35分なので余裕があると言えばあるのですが、ビルドにかかる時間は少なければ少ない方が良いです。mavenの場合は .m2 をキャッシュ用のディレクトリにシンボリックリンクすることで対応した *2 のですが、sbtでも同じ考え方で行けるかどうかは要件証です。テストの問題が片付いたら検証してみます*3。