今回もしつこくHeroku+Symfony2ネタです。
前回の記事で、HerokuでSymfony2アプリケーションをデプロイできるようになりましたが、そういえばテストを通していないなと思いました。
ちゃんとしたプロダクトを作るならテストは必須!ということで、オンラインCIサービスのTravis CIと連携してテストを通した後にHerokuに自動的にデプロイできるようにしてみます。
また、テストのカバレッジレポートを画面で確認できるように、Coverallsとも連携するようにしました。
今回の目標
- GitHubにあるSymfony2アプリケーションをTravis CI経由でHerokuにデプロイできるようにする
- Travis CIとCoverallsと連携してテストのカバレッジを確認できるようにする
環境
前提条件
- ソースコードがGitHubのPublicリポジトリとして登録されていること。プライベートリポジトリだとTravis CIは有料になります
- Herokuアプリケーションとして動かせるようにしておくこと
- HerokuでSymfony2をデプロイして動かせるようにした を参考にHerokuでアプリケーションを動かせるようにしておいてください
Travis CIとは
簡単にいえば、オンラインでCI(継続的インテグレーション)してくれるサービスです。最近はTravis CIの他、CircleCI、wercker、drone.ioなどが多くリリースされています。
CIツールといえば、Jenkinsを思い浮かべる人も多く、 僕自身も仕事でJenkins先生には日頃からお世話になっている定番ツールですが、自前でJenkinsをインストールしたりプラグイン入れたり細かい設定をするのが多く、個人開発用に使うのは敷居が高いなと思います。
その点、オンラインCIサービスだとデプロイするのに必要なツールなどが用意されており、設定ファイルをリポジトリに置くだけで実行することができてしまいます。また、各種ツールをアップグレードしたりなどメンテナンスする必要がないのも大きなメリットです。
多くのオンラインCIサービスがありますが、今回は次の理由でTravis CIを使ってみました。
- Travis CIを使っている参考記事も多く調べやすい
- Travis CIとHerokuの連携方法も簡単そう
- 参考URL : Travis CI: Heroku Deployment
- パブリックなリポジトリなら無料でできる
では、実際に設定していきます。
ローカル環境でテストが通るようにする
何はともあれ、テストが通らないとデプロイも通らないので、まずテストを通すようにします。
テストコードが無い人はテストコードを書いてください。
$ cd ./symfony2
$ phpunit -c app
テストが通ったら一旦、GitHubにPushしておきます。
$ git push origin master
Travis CIとGitHubを連携する
ブラウザ上で操作します。
- Travis CIにGitHubアカウントでログインする
- 右上のアカウント名 →「Accounts」をクリックする
- Travis CIと連携したいリポジトリの右側のスイッチを「ON」にする
もし、表示されていない場合は、「Sync now」ボタンをクリックする
HerokuのAPIキーを暗号化する
Travis CIでHerokuへデプロイする際にAPIキーが必要ですが、後述する設定ファイル(.travis.yml)にAPIキーをそのまま記述するのはセキュリティ的に危険なので暗号化します。
travisコマンドが必要なのでインストールします。
$ gem install travis
$ travis --version
1.6.16
HerokuのAPIキーを取得します。
$ heroku auth:token
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"が生のAPIキーです。
HerokuのAPIキーを暗号化します。
$ travis encrypt -r [リポジトリ名] HEROKU_API_KEY=[HerokuのAPIキー]
# e.g.
$ travis encrypt -r ohsawa0515/heroku-symfony2 HEROKU_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
secure: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXX..."が暗号化されたHerokuのAPIキーとなります。
.travis.yml を編集してgit pushする
Travis CIの設定を設定ファイル(.travis.yml)で行います。
ComposerでSymfony2をインストールするとすでに.travis.yml が入っているため、それを使います。
# 言語をPHPに指定します
language: php
# PHPのバージョンを指定します
# 複数バージョンを指定すると、それぞれのバージョンに対してTravis CIのビルドが実行されます
php:
- 5.5
# CIする対象のブランチを指定します
# PullRequestされたブランチは例外で、どんなブランチでもビルドが実行されます
branches:
only:
- master
- develop
# CIする前に実行したいコマンドなどを指定します
before_script:
# セッション管理にMemcachedモジュールを使っているため、モジュールをインストールしています
- printf "\n" | pecl install memcached
- echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
# composer.jsonに記載されているモジュールなどをインストールします
- composer install -n --dev
# CIする際に実行したいコマンドを指定します
# ここでPHPUnitを実行しています
script:
- mkdir -p build/logs
- phpunit -c app
# テスト実行後にデプロイ先を設定します
deploy:
# デプロイ先をHerokuに指定します
provider: heroku
# 先ほど暗号化したHerokuのAPIキーを指定します
api_key:
secure: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# デプロイしたいブランチとHerokuのアプリケーションを指定します
# 指定した以外のブランチではHerokuにデプロイされません
app:
# developブランチでheroku-symfony2-0515というHerokuアプリケーションにデプロイする
develop: heroku-symfony2-0515
これで実際に動くか確認してみます。
$ git add -A && git commit -m "add heroku deploy"
$ git push origin master
GitHubに$ git push
すると自動的にTravis CIでビルドが実行され、テストが正常に通るとHerokuにデプロイされるようになります。
正常に終了すると、以下の図のように"passed"になります。
Coverallsと連携する
次にテストのカバレッジをレポートしてくれるCoverallsと連携してみます。
連携するためには、Coveralls にアクセスし、GitHubアカウントでサインインします。
リポジトリ一覧が表示されるので、コードカバレッジを表示させたいリポジトリをONにすればアカウント上の連携は完了です。
composerでphp-coverallsをインストール
Coverallsを使うにはAPIを使う必要があるのですが、PHPでCoverallsを実行してくれるphp-coverallsを使います。
# composer.json
{
"require-dev": {
# 以下追記
"satooshi/php-coveralls": "dev-master"
}
}
composer install
かcomposer update
すればインストールは完了です。
app/phpunit.xml.dist を編集する
カバレッジを参照できるようにapp/phpunit.xml.dist
を編集します。
<?xml version="1.0" encoding="UTF-8"?>
<!-- http://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit
backupGlobals = "false"
backupStaticAttributes = "false"
colors = "true"
convertErrorsToExceptions = "true"
convertNoticesToExceptions = "true"
convertWarningsToExceptions = "true"
processIsolation = "false"
stopOnFailure = "false"
syntaxCheck = "false"
bootstrap = "bootstrap.php.cache" >
<testsuites>
<testsuite name="Project Test Suite">
<directory>../src/*/*Bundle/Tests</directory>
<directory>../src/*/Bundle/*Bundle/Tests</directory>
</testsuite>
</testsuites>
<!-- 追記 -->
<logging>
<log type="coverage-clover" target="../build/logs/clover.xml"/>
</logging>
<!-- 追記終わり -->
<!-- ...以下省略 -->
</phpunit>
Symfony2の場合、phpunit.xml.dist
がapp/
以下にあるため、targetのパス(../build/logs/clover.xml
)に注意してください。
.travis.yml を編集する
先ほどの.travis.yml
を編集します。
language: php
php:
- 5.5
branches:
only:
- master
- develop
before_script:
- printf "\n" | pecl install memcached
- echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- composer install -n --dev
script:
- mkdir -p build/logs
- phpunit -c app
# 以下を追記
- php vendor/bin/coveralls -v
deploy:
provider: heroku
api_key:
secure: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
app:
develop: heroku-symfony2-0515
README.mdには、after_script
に設定していますが、after_script
だとHerokuでデプロイした後に実行されてしまい、何故か動かなかったので、script
に書きました。
.coveralls.yml を作成する
Coverallsの設定を.coveralls.yml
に記述して、Symfony2ディレクトリ直下(.travis.yml
と同じ階層)に置きます。
service_name: travis
src_dir: src
coverage_clover: build/logs/clover.xml
json_path: build/logs/coveralls-upload.json
exclude_no_stmt: true
ローカルでCoverallsを実行($ php vendor/bin/coveralls -v
)する場合、repo_token
というパラメータにCoverallsにトークンを設定しますが、Travics CI経由で実行する場合はrepo_token
パラメータを設定しません。
この辺りを勘違いしてrepo_token
にトークンを設定した状態でデプロイした際、Travis CIのログに「Requirements are not satisfied.」と表示され、Coverallsの方もカバレッジが表示されませんでした。結局、php-coverallsのソースを見てやっと原因が突き止めました。
これでリポジトリにCommitしてGitHubにPushすれば、Travis CIのビルド実行後にCoverallsでテストカバレッジが表示されるようになるはずです。
こんな風にカバレッジが表示されるようになります。カバレッジが16%と低いのはデモ用に作ったコードだからです(と言い訳してみる)。
"BUILD"列か"COMMIT"列のリンク先をクリックすると、カバレッジの詳細が表示されます。ファイル一覧も表示できてテストがどのぐらいカバーできているかも分かるようになっています。
ファイルのリンク先をクリックすると、そのファイル内の詳細も見れるのですが・・・
パスが間違っているのか表示されません。
そこで、「Git repo root directory」を空にして、「Git repo sub directory」に「src」と入力してUPDATEします。
パスが合えば、ソースコードが表示され、行単位でテストがカバーした範囲が分かるようになります。
赤く覆われている行はテストがカバーしていない行です。
最後に
GitHub、Travis CI、Coverallsと連携してSymfony2アプリケーションをHerokuにデプロイするように設定できました。
他にもライブラリのバージョンアップを通知してくれるversioneyeやアプリケーションのソースコードをスキャンして脆弱性を診断してくれるSensioLabsInsightなどもあり、自分で一から環境を構築しなくてもすぐに開発できてしまう環境ができてとても便利ですね。
多くのサービスがリリースされ、開発効率が向上できる機会が増えているので、日頃から情報収集して乗り遅れないようにしたいものです。