GitHub Actionを使って自前Docker内で自動テスト


## GitHub Actionを使って自前Docker内で自動テスト
GitHubで管理しているDockerとLaravel_PJがあります。そのLaravel_PJで作成されたプルリクをトリガーにDocker内でPHPUnitを回すというようなGitHub Actionを作成しました。
要はDocker内にLaravel_PJを突っ込んでPHPUnitを回してます。

Dockerは各環境によるので割愛

## 環境
 - docker-compose v3
 - [php-fpm] php:7.3.0-fpm-alpine3.8
 - [db] mysql:5.7
 - Laravel v6.0
 - phpunit v8.3


### 作成手順

1. リポジトリをクローン出来る様にPersonal access tokensを設定しておきます
  権限はrepoにチェックで大丈夫です
  https://github.com/settings/tokens

2. テスト対象のリポジトリのSettingタグからSecretsを選択し、`GITHUB_PAT`に先程のtokenを、`SLACK_WEBHOOK`に通知したいslackのwebhookを設定します
参考：[SlackのWebhook URL取得手順](https://qiita.com/vmmhypervisor/items/18c99624a84df8b31008)

3. テスト対象のリポジトリに下記ファイルを保存します。

4. envには下記値を設定します
  PJ_ACTOR: [GitHubのアカウント名]
  PJ_REPO: [テスト対象となるPJ]
  PJ_DOCKER_REPO: [テスト対象となるPJを動かしているDocker]

5. .env.exampleにはAPP_KEY、Dockerのdbにアクセスするusername、password等を設定します

github/workflows/main.yml

```yml:

name: Test CI

on:
  pull_request:
    types: [opened, synchronize]
    branches:
      - 'master'
      - '!analysis-**' # StyleCIを除外

env:
  PJ_ACTOR: my-account
  PJ_REPO: test-project
  PJ_DOCKER_REPO: test-project-docker
  GITHUB_PAT: ${{ secrets.GITHUB_PAT }}
  SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Clone ${{ env.PJ_REPO }}
        uses: actions/checkout@v1
      - name: Clone ${{ env.PJ_DOCKER_REPO }}
        uses: actions/checkout@v1
        with:
          repository: ${{ env.PJ_ACTOR }}/${{ env.PJ_DOCKER_REPO }}
          ref: refs/heads/master
          token: ${{ env.GITHUB_PAT }}
      - name: Project copy
        run: |
          cd ${GITHUB_WORKSPACE} && cd ../
          cp -pr ./${PJ_REPO} ./${PJ_DOCKER_REPO}/www/${PJ_REPO}
      - name: Docker set up
        run: |
          cd ${GITHUB_WORKSPACE} && cd ../
          cd ./${PJ_DOCKER_REPO}
          docker-compose build php-fpm
          docker-compose up -d php-fpm
      - name: Project set up
        run: |
          cd ${GITHUB_WORKSPACE} && cd ../
          cd ./${PJ_DOCKER_REPO}/www/${PJ_REPO}
          composer install
          composer dump-autoload
          cp -p .env.example .env
      - name: Execute tests 
        run: |
          cd ${GITHUB_WORKSPACE} && cd ../
          cd ./${PJ_DOCKER_REPO}
          # mysql起動確認。起動していなければテスト実行不可。mysqlが立ち上がるまで20秒ほどかかる
          docker-compose exec -T db service mysql status
          docker-compose exec -T php-fpm sh -c "cd /var/www/${PJ_REPO}/vendor/bin/phpunit"
      - name: Slack Notification
        uses: homoluctus/slatify@master
        if: always()
        with:
          type: ${{ job.status }}
          job_name: '*[${{ env.PJ_REPO }}] Unit Test*'
          mention: 'here'
          mention_if: 'failure'
          channel: 'sys_ci'
          icon_emoji: ''
        env:
          SLACK_WEBHOOK: ${{ env.SLACK_WEBHOOK }}

```

## ポイント

#### イベントについて
前提として、プルリクを投げたブランチ上でテストが走ります

- opend：プルリクが作成された時
- synchronize：プルリクしているブランチが更新された時

他にもイベントはありますが、自分が確認したところはこんな感じでした

- edited：プルリクのタイトルや、マージ向き先が変更になった時
- closed：プルリクが対象ブランチにマージ・クローズされた時

```yaml
on:
  pull_request:
    types: [opened, synchronize]
```

参考：[ワークフローをトリガーするイベント](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows)

#### envについて
yaml上で設定した変数を使用する場合は、`${{ env.PJ_ACTOR }}`のように、step内のbashで使用する場合は`${PJ_ACTOR}`のように（bashで変数を使用する時と同じ）する必要があります

参考
・[環境変数の利用](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/using-environment-variables#about-environment-variables)
・[GitHub Actions のコンテキストおよび式の構文](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions)

### DockerのMysqlについて
GitHub Actionsを使う以外にもCI/CDを作成する際のポイントだと思うのですが、Mysqlは立ち上がるのに20秒ほどかかるようなので、そこら辺を考慮します。（かなりハマった）立ち上がりまでsleepするとよいかもです。

### Slack通知について
GitHub Actionには個別で使用できるaction機能があるのですが、Slack通知にslatifyを使わせて頂いております！まさに欲しかった機能通りで、痒いところに手が届く〜

参考：[【GitHub Actions】Slack通知用のActionsをTypeScriptで開発してみた](https://qiita.com/homines22/items/0bc6c17e038b35fc8113)

#### 感想
GitHibActionでDockerを使う場合はGitHub側が用意したものを使うべきなのか？Docker Hubで管理するべきなのか？どれがベストなんですかね。Dockerについても勉強していきたいです〜