EC-CUBE で使っている .travis.yml を解説するよ

[Docker + Travis CI で Codeception CI をしよう](http://qiita.com/nanasess/items/798aea2ecdd7d79b93d0) に引き続きの Travis CI ネタです。

EC-CUBE3 では、 Travis CI を使用して、ユニットテストを自動化しています。
どんなことをするかは [.travis.yml](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml) に書かれていますが、コメントも乏しいので解説してみます。

## 各セクションの解説

### [git](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L3-L4)

```yaml
git:
  submodules: false
```

現在は、 git submodule を使用していないのですが、 submodule を取得しないよう、念のために false としています。

### [language](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L6)

```yaml
language: php
```

PHP のテストをしたいので php を指定しています。

### [cache](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L8-L11)

```yaml
cache:
  directories:
    - vendor
    - $HOME/.composer/cache
```

テストの準備を高速化するため、主に Composer 関連のファイルをキャッシュしています。

### [php](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L12-L18)

```yaml
php:
  - 5.3
  - 5.4
  - 5.5
  - 5.6
  - 7.0
  - 7.1
```

PHP5.3.29 〜 7.1.x でテストを実行する設定です。
EC-CUBE3系 の最低動作環境は PHP5.3.9 ですが、 Travis CI ではサポートされないバージョンとなってしまいました。

### [matrix](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L20-L44)

[Build matrix](https://docs.travis-ci.com/user/customizing-the-build#Build-Matrix) セクションは、PHP のバージョンや環境変数を掛け合わせてテストする設定です。
順番に解説します。

#### [fast_finish](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L21)

```yaml
fast_finish: true
```

いずれかのテストに失敗したら、すぐにテストのジョブを失敗とマークする設定です。

#### [include](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L22-L26)

```yaml
  include:
    - php: 7.0.12 # for coverrage
      env: DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
      sudo: required
      dist: trusty
```

個別にテストに含める設定を記述します。

ユニットテストの実行後、 [Coveralls](https://coveralls.io/github/EC-CUBE/ec-cube?branch=master) を使用して、テストカバレッジを計測するための設定です。

[phpdbg を使用してカバレッジレポートを出力](http://qiita.com/nanasess/items/f5f8483e92c76ef408ff) するのですが、 Travis CI では [Ubuntu Trusty のイメージ](https://docs.travis-ci.com/user/trusty-ci-environment/)  を使用する必要があります。 *(Precise のイメージは Segmentation fault になってしまいます...*

また、ここでは `php: 7.0.8` 以降を指定する必要があります。[PHP7.0.7 のバグのため](https://github.com/sebastianbergmann/php-code-coverage/issues/446) カバレッジ出力時にエラーとなってしまうため、個別にマイナーバージョンまで指定しています。


#### [exclude](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L27-L39)

```yaml

  exclude:
    - php: 5.3
      env: DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
    - php: 5.4
      env: DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
    - php: 5.5
      env: DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
    - php: 5.6
      env: DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
    - php: 7.0
      env: DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
    - php: 7.1
      env: DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
```

ちょっと長いですが、 include で指定した phpdbg のテストを、各バージョンの PHP で実行しないようにする設定です。

#### [allow_failures](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L40-L44)

```yaml
 allow_failures:
    - env: DB=sqlite
    - php: 7.1
    - php: 7.0.12
      env: DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
```

ここに記述したテストが失敗しても、ジョブ全体としては失敗と記録しません。
主に、開発用途や、実験的な環境を記述します。
SQLite3, PHP7.1, 前述のカバレッジ出力用のテストを設定しています。

### [env](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L46-L50)

```
env:
  - DB=mysql USER=root DBNAME=myapp_test DBPASS=' ' DBUSER=root
  - DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres
  - DB=pgsql USER=postgres DBNAME=myapp_test DBPASS=password DBUSER=postgres PHP_SAPI=phpdbg
  - DB=sqlite
```

.travis.yml で使用する環境変数のバリエーションを記述します。
主にデータベースの接続設定です。

### [install](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L52-L54)

```
install:
  - gem install mime-types -v 2.99.1
  - gem install mailcatcher
```

テストに使用するミドルウェア等をインストールする設定です。
メールの送受信をテストするための mailcatcher をインストールする設定を記述しています。
`gem install mime-types -v 2.99.1` は、 gem の依存関係で mailcatcher のインストールに失敗しないようにする対策です。

### [before_script](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L56-L63)

```yaml
before_script:
  - CODENAME=$(lsb_release -c -s)
  - if [[ $PHP_SAPI != 'phpdbg' ]] || [[ $CODENAME = 'trusty' ]]; then phpenv config-rm xdebug.ini ; fi
  - if [[ $PHP_SAPI = 'phpdbg' ]]; then echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini ; fi
  - composer self-update || true
  - composer install --dev --no-interaction -o
  - php ./eccube_install.php $DB none
  - mailcatcher
```

テスト実行前に、実行するスクリプトです。順番に解説します。

```yaml
- CODENAME=$(lsb_release -c -s)
```

trusty の環境か、 precise の環境かを取得します。

```yaml
- if [[ $PHP_SAPI != 'phpdbg' ]] || [[ $CODENAME = 'trusty' ]]; then phpenv config-rm xdebug.ini ; fi
```

xdebug を無効化して、テストを高速化します。 
*おそらく if 文の条件は不要ですが、歴史的な理由で残っています...*

```yaml
  - if [[ $PHP_SAPI = 'phpdbg' ]]; then echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini ; fi
```

phpdbg は、とてもたくさんのメモリを使用するため、 `memory_limit=-1` としています。

```yaml
- composer self-update || true
```

念のため、 composer を最新化します。

```yaml
- composer install --dev --no-interaction -o
- php ./eccube_install.php $DB none
```

composer install の実行後、 EC-CUBE をインストールします。

```yaml
- mailcatcher
```

最後に mailcatcher を起動して、準備完了です!

### [script](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L65-L67)

```yaml
script:
  - if [[ $PHP_SAPI = 'phpdbg' ]] && [[ $CODENAME = 'trusty' ]]; then phpdbg -qrr ./vendor/bin/phpunit --coverage-clover=coverage.clover ; fi
  - if [[ $PHP_SAPI != 'phpdbg' ]]; then phpunit ; fi
```

ユニットテストを実行するスクリプトです。
1行目は、 trusty の環境でのみ実行します。 phpdbg でカバレッジレポートを出力します。
2行目は、 phpdbg 以外の環境で PHPUnit を実行します。
テストの高速化のため、 `vendor/bin/phpunit` を使用せず、 Travis CI にインストールされた phpunit を実行します。

### [after_script](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L69-L71)

```yaml
after_script:
  - if [[ $PHP_SAPI = 'phpdbg' ]]; then wget https://scrutinizer-ci.com/ocular.phar ; fi
  - if [[ $PHP_SAPI = 'phpdbg' ]]; then php ocular.phar code-coverage:upload --format=php-clover coverage.clover ; fi
```

テスト実行後、メトリクス計測のため [Scrutinizer へレポートを送信します](https://scrutinizer-ci.com/g/EC-CUBE/ec-cube/?branch=master)

### [after_success](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L73-L74)

```yaml
after_success:
  - if [[ $PHP_SAPI = 'phpdbg' ]]; then php vendor/bin/coveralls -v -x coverage.clover ; fi
```

テストに成功した場合のみ、実行します。
phpdbg の環境のみ、 coveralls へカバレッジレポートを送信します。


### [after_failure](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L76-L77)

[この行](https://github.com/EC-CUBE/ec-cube/blob/master/.travis.yml#L76-L77) のコメントをはずすと、テストが失敗した時に大量のログを表示してくれます。デバッグ用途には便利ですが、大量すぎて、ブラウザが固まってしまうこともあります。ご利用は計画的に...

## まとめ

EC-CUBE3 のリリース当初は、比較的シンプルだった .travis.yml も、徐々に肥大化し、やってることも黒魔術化してきてしまいました。
Travis CI は、大変多機能で、工夫し甲斐があるのですが、頑張りすぎると、引き継ぎなどで苦労しそうです...
今回のアドベントカレンダーは、解説記事をまとめるのに良い機会でしたが、引き継ぎに困らないドキュメントを目指して、日々精進していきたいものです。