GitHub ActionsでLaravelのテストをするのにMySQLを利用する

GitHub ActionsでLaravelテストするのにMySQLを利用するのにハマったのでメモ。


## 前提

[こちらの記事](https://qiita.com/kai_kou/items/4f850f7308eb0d3e0b48)で利用したLaravelプロジェクトとGitHub Actionsのワークフローをカスタマイズします。


## 手順

### ワークフロー作成

以下のようにワークフローを作成します。

```yaml
name: Laravel

on:
  push:
    branches:
    - main
    - feature/**
  pull_request:
    branches:
    - develop
    - main

jobs:
  laravel-tests:

    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:5.7
        ports:
          - 3306:3306
        env:
          MYSQL_ROOT_PASSWORD:
          MYSQL_DATABASE: hoge_app
          MYSQL_USER: root
          MYSQL_PASSWORD:
          MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
        options: --health-cmd "mysqladmin ping -h localhost" --health-interval 20s --health-timeout 10s --health-retries 10

    steps:
    - uses: actions/checkout@v2
    - name: cache vendor
      id: cache
      uses: actions/cache@v1
      with:
        path: ./vendor
        key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
        restore-keys: |
          ${{ runner.os }}-composer-
    - name: composer install
      if: steps.cache.outputs.cache-hit != 'true'
      run: composer install -n --prefer-dist
    - name: copy .env
      run: cp .env.example .env
    - name: generate key
      run: php artisan key:generate
    - name: migrate
      run: php artisan migrate
      env:
        DB_HOST: 127.0.0.1
    - name: Execute tests (Unit and Feature tests) via PHPUnit
      env:
        DB_HOST: 127.0.0.1
      run: vendor/bin/phpunit
```

#### MySQLの設定

`services`で`mysql`を定義します。環境変数は`.env`の内容を反映できないので、そのまま指定します。
GitHubのSecretsを利用するとパスワードはそちらから指定することもできますが今回はプロジェクトの`.env.example`の内容と同じにしています。

GitHubのSecretsを活用して、GitHub Actionsで安全に機密情報を扱う - Qiita
https://qiita.com/developer-kikikaikai/items/60b209c065f076dca7a1

`options`でMySQLが起動したかヘルスチェックするようにします。

```yaml
    services:
      mysql:
        image: mysql:5.7
        ports:
          - 3306:3306
        env:
          MYSQL_ROOT_PASSWORD:
          MYSQL_DATABASE: hoge_app
          MYSQL_USER: root
          MYSQL_PASSWORD:
          MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
        options: --health-cmd "mysqladmin ping -h localhost" --health-interval 20s --health-timeout 10s --health-retries 10
```

#### マイグレーションとテスト

`env`で`DB_HOST`を指定します。開発環境だと`.env.example`で`mysql`とDockerコンテナの名前を指定していますが、それだとGitHub上だと接続できません。

```yaml
    - name: migrate
      run: php artisan migrate
      env:
        DB_HOST: 127.0.0.1
    - name: Execute tests (Unit and Feature tests) via PHPUnit
      env:
        DB_HOST: 127.0.0.1
      run: vendor/bin/phpunit
```

### ローカルで動作確認

こちらのツールを利用するとローカル環境で動作確認ができます。

nektos/act: Run your GitHub Actions locally 🚀
https://github.com/nektos/act#installation


1点ハマりどころがあり、GitHub Actionsが提供するサービスコンテナがnektos/actでは現状未実装となるため、ローカルとGitHubとで差異があります。

サービスコンテナについて - GitHub Docs
https://docs.github.com/ja/actions/guides/about-service-containers

Github actions - Services fails locally · Issue #247 · nektos/act
https://github.com/nektos/act/issues/173

ただ、ワークフローで`DB_HOST: 127.0.0.1`と指定することで、開発環境のMySQLへ接続できるので、開発環境のDockerコンテナを起動したまま、`act`コマンドを実行してあげるとローカル環境でもワークフローが実行できます。

```console
> cd <プロジェクトのディレクトリ>
> ./vendor/bin/sail up -d
> act -P ubuntu-latest=nektos/act-environments-ubuntu:18.04
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48549/959afd3b-f1bc-d9e6-c659-359695d3afd9.png)
実行結果をみると、`Run migrate`は実行されているものの、マイグレーション自体は実行されていないことが確認できます。（開発環境でマイグレーションが実行済みの場合)

開発環境のDockerコンテナを落とすと、ワークフローがエラーになることも確認できます。

```console
> ./vendor/bin/sail down
> act -P ubuntu-latest=nektos/act-environments-ubuntu:18.04
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48549/d69e8c24-eb88-e8ce-2511-835996e2ece8.png)


### GitHub上で動作確認

ワークフローをGitHubリポジトリにpushしてワークフローが動作するか確認します。


```console
> git branch feature/use-mysql-on-github-actions
> git checkout feature/use-mysql-on-github-actions
> git add .github/workflows/unittest.yml
> git commit -m 'Fix: GitHub ActionsのワークフローでMySQLを利用するようにしました。'
> git push git push --set-upstream origin feature/use-mysql-on-github-actions
```

GitHubで確認するとエラーなくテストが実行できたことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48549/cb30ef53-3b3f-4a96-cfa0-f4cf4f4abd45.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48549/71636e8f-aacb-b092-921c-7da031f2e6cd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48549/a197d46d-21a7-72ef-30e2-0abfdc8b9f4c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48549/53b4f6cd-4dc2-1001-d9fb-3396ada6bd01.png)
やったぜ


## 参考

GitHub Actionsを利用してLaravelのテストを自動化してみた - Qiita
https://qiita.com/kai_kou/items/4f850f7308eb0d3e0b48

GitHubのSecretsを活用して、GitHub Actionsで安全に機密情報を扱う - Qiita
https://qiita.com/developer-kikikaikai/items/60b209c065f076dca7a1

nektos/act: Run your GitHub Actions locally 🚀
https://github.com/nektos/act#installation

Number of ways to setup database in Github actions | by Darren Liew | Medium https://medium.com/@ldarren/number-of-ways-to-setup-database-in-github-actions-2cd48df9faae

GitHub Actionsを使ってLaravelアプリケーションをCI/CDする | SEEDS Creators' Blog | 株式会社シーズ https://www.seeds-std.co.jp/blog/creators/2020-08-19-233031/

Mysql service never comes up healthy in action - Code to Cloud / GitHub Actions - GitHub Support Community
https://github.community/t/mysql-service-never-comes-up-healthy-in-action/16890