リポジトリ直下に複数Laravelプロジェクトがある場合のCircleCI(1.0)設定

CircleCI(1.0)を使ってテストを実行させる場合、リポジトリ＝プロジェクトという場合はリポジトリの直下にcomposer.jsonやphpunit.xmlがあるので特に何も意識しなくともCircleCIがよしなにしてくれるのですが、リポジトリ内に複数のプロジェクトがあり直下にcomposer.jsonやphpunit.xmlがない場合、それぞれのプロジェクトでcomposer installやphpunitの実行しなければいけないのだけれどそこの設定でハマったのでメモ。

## 環境

|名前|バージョン|
|---| -------- |
|PHP | 7.1.6    |
|Laravel| 5.5.14 |
|PHPUnit | 6.4.1    |
|composer | 1.5.1    |

CircleCIの環境は以下になります。

|名前|バージョン|
|---| -------- |
|CircleCI | 1.0    |
|Build Environment - Build macOS project| off |
|Build Environment - OS to use for builds | Ubuntu 14.04 (Trusty)    |
|PHP | 7.1.6    |

## 状況

exampleリポジトリ内で複数のLaravelプロジェクトが

* path/to/common
* path/to/project1
* path/to/project2
* path/to/project3

と４つ存在する場合についてです。
以下ハマった点をひとつずつ説明します。

## 指定のディレクトリのcomposer.jsonをどうやって指定する？

通常だとリポジトリ直下にcomposer.jsonがあるので明示的にcomposer installしなくともCircleCIが勝手にやってくれるのですが、今回のケースでは直下にcomposer.jsonがありませんでした。
こういった場合は`--working-dir`オプションを利用します。
実際には以下のコマンドになります。

```
$ composer install --dev --no-interaction --working-dir=path/to/common
```

composer.jsonが存在するディレクトリを指定します。

## 指定のphpunit.xmlを使いたい

こちらも通常は直下にphpunit.xmlがあるので意識することはないですが、指定するオプションはあります。

```
$ path/to/common/vendor/bin/phpunit -c path/to/common/phpunit.xml
```

これでphpunit.xmlを指定することができます。

## テスト用のDB接続設定を使うには？

この場合はmigrateやseed実行時に`--env`オプションと`--database`オプションを利用すればよいです。
テスト用なのであらかじめ定義しておいたtestingを利用します。

```
php path/to/common/artisan migrate --env=testing --database=testing
php path/to/common/artisan db:seed --env=testing --database=testing
```

## 実際の設定

circle.ymlと各プロジェクトのデータベース接続設定は以下のものになります。
まずはcircle.yml。

```circle.yml
machine:
  timezone: Asia/Tokyo
  php:
    version: 7.1.6
  environment:
    DB_HOST_TESTING: 127.0.0.1
    DB_DATABASE_TESTING: circle_test
    DB_USERNAME_TESTING: ubuntu
    DB_PASSWORD_TESTING: ''

database:
  override:
    - php path/to/common/artisan migrate --env=testing --database=testing
    - php path/to/common/artisan db:seed --env=testing --database=testing

dependencies:
  cache_directories:
    - path/to/common/.composer/cache
  pre:
    - composer config -g github-oauth.github.com $GITHUB_OAUTH_TOKEN
    - echo "memory_limit = 2048M" > /opt/circleci/php/$(phpenv global)/etc/conf.d/memory.ini 
  override:
    - composer install --dev --no-interaction --working-dir=path/to/common
    - composer install --dev --no-interaction --working-dir=path/to/project1
    - composer install --dev --no-interaction --working-dir=path/to/project2
    - composer install --dev --no-interaction --working-dir=path/to/project3

test:
  override:
    - path/to/common/vendor/bin/phpunit -c path/to/common/phpunit.xml
    - path/to/project1/vendor/bin/phpunit -c path/to/project1/phpunit.xml
    - path/to/project2/vendor/bin/phpunit -c path/to/project2/phpunit.xml
    - path/to/project3/vendor/bin/phpunit -c path/to/project3/phpunit.xml
```

testingのデータベースに接続するために`environment`で環境変数を設定しています。
CircleCIのMySQLのデフォルトの設定をそのまま利用しています。

* ホストは`127.0.0.1`
* DB名は`circle_test`
* ユーザは`ubuntu`
* パスワードは空文字を指定

これらがCircleCIのMySQLのデフォルトの設定値なのでそれを環境変数に設定します。

それぞれのLaravelプロジェクトのconfig/database.phpは以下のように
テスト用の接続設定の`testing`を定義しておきます。

```config/database.php
<?php

return [

    'default' => env('DB_CONNECTION', 'mysql'),

    'connections' => [

        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],

// ★ここから大事
        'testing' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST_TESTING', '127.0.0.1'),
            'port' => env('DB_PORT_TESTING', '3306'),
            'database' => env('DB_DATABASE_TESTING', 'db_testing'),
            'username' => env('DB_USERNAME_TESTING', 'testuser'),
            'password' => env('DB_PASSWORD_TESTING', ''),
            'unix_socket' => env('DB_SOCKET_TESTING', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],
// ★ここまで大事
    ],

    'migrations' => 'migrations',

    'redis' => [

        'client' => 'predis',

        'default' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => 0,
        ],

    ],

];
```

このように設定することによりcircle.ymlで定義した環境変数を利用することができます。

また、composer installの実行時間を短縮やテストで利用するメモリを増やすために以下の設定をしています。

```yml
dependencies:
  cache_directories:
    - path/to/common/.composer/cache
  pre:
    - composer config -g github-oauth.github.com $GITHUB_OAUTH_TOKEN
    - echo "memory_limit = 2048M" > /opt/circleci/php/$(phpenv global)/etc/conf.d/memory.ini 
```

あらかじめCircleCIの管理画面から`$GITHUB_OAUTH_TOKE`を設定しておく必要があります。
設定についてはCircleCIのPROJECTSのsettingsよりEnvironment Variablesから設定します。

それぞれの意味については記事下部記載のエントリがわかりやすいです。
GitHubからのパッケージ取得をアーカイブで行うようにしたり、composerをキャッシュしておいたりしています。

## 参考

[CircleCI で composer を高速化させる](http://engineering.otobank.co.jp/entry/2015/11/24/172804)