Github Actionsを使用してJestを自動で実行する

# はじめに

  現在関わっているプロジェクトにて、jestで書かれたテストケースの総数が増えてきたということもあり、
ソースコードに変更を加えるたびに、ローカル環境で全てのテストを手動で実行していてると、全テストの実行完了までに少し時間がかかってしまったり、現在自分が改修を行なっているソースコードとは直接関係のないテストの実行を忘れてしまうという事態がちらほら発生し始めました。

  そこで、Githubにソースコードをpushした際に自動でテストを実行できればマージ前に全テストの実行を忘れることなく安全にマージを行えると思いCI環境の整備を進めようと考えました。

  自動テストを行うためのCI環境を整備するにあたって、私自身が業務で今まで使用したことのないGithub Actionsを使用して設定を行うことになりました。
（既に社内の別プロジェクトではGithub Actionsの導入実績がある & 既に安定して運用を行なっている。）
  以前に業務で使用したことのあるCIツールとの違いなどの軽くみていきながら、Github Actionsで自動テストを実行するための設定を解説していきたいと思います。

# 使用した技術スタック
* 言語：Typescript
* ORM:Prisma
* サービス間通信：gRPC
* テストフレームワーク：Jest

プロジェクトの現状を簡単に説明すると、
モノリスで書かれた既存プロジェクトのリプレイス作業を行っており、リプレイス後のソースコードに関しては、同一リポジトリ内にて、monorepoに移行される想定になっています。

# 設定ファイル
```yml:test-grpc.yml
name: Typescript gRPC Test

on:
  push:
    paths:
      - "src/backend/**"

defaults:
  run:
    shell: bash
    working-directory: src/backend

jobs:
  typescript-gRPC:
    name: Typescript gRPC Test
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:5.7
        ports: ["3306:3306"]
        env:
          MYSQL_ROOT_PASSWORD: pass
          MYSQL_DATABASE: test

    steps:
      - uses: actions/checkout@v3

      - name: Set up Node
        uses: actions/setup-node@v3
        with:
          node-version: "16"

      - name: Install dependencies
        run: yarn

      - name: Run tests
        env:
          DATABASE_URL: mysql://root:pass@localhost:3306/test
        run: |
          yarn proto
          yarn prisma migrate dev
          yarn test
```

# 他のCIツールとの比較
 ## Github Actions
  GithubでCI環境を整備する際の、デファクトスタンダードになってきている印象です。
CIの実行結果（CI上でのコマンド処理の成否など）をGIthub内の対象リポジトリのプルリクのページからタブを切り替えてすぐに閲覧できるのはなかなか使い勝手が良いのではないかと思います。

https://docs.github.com/cn/actions

## Gitlab Runner
  GitlabにてCI環境を整備する際には、最適だと思います。

https://docs.gitlab.com/runner/

## CirecleCI
  CirecleCIを使用してCI環境を整備する際には、CirecleCI側からGithub側にアクセスできるように、tokenを発行するなどの設定を行う必要があり、Github Actionsと比較した際に少し手間がかかる印象があります。

https://circleci.com/docs/ja/

  上記で、3つのCIツールの比較を行なっていますが、いずれのCIツールを使用したとしても、CI上で実行したい一般的な処理項目は実現が可能ではあると思います。
社内のリモートリポジトリに、GithubもしくはGitLabのどちらを採用しているのかなどを考慮した上で、使い勝手の良し悪しでどのCIツールを採用するのかを決定すれば良いのではないかと思います。

## 導入する際の学習コスト
以前、Gitlab Runnerを使用して既存プロジェクトにCI環境を導入したことがありますが、 Gitlab Runnerと Github Actionsのどちらもyml形式で設定を行える、かつGitlab Runnerで培ったCIの基礎的な知見が応用可能であったので、学習コストは低いのではないかと思います。
ただ、Github Actions特有の構文やymlファイルの中で使用されているツールのような類のものに関して、公式ドキュメントや参考資料を参照しながらキャッチアップを行う必要はあると思います。

社内で既に設定&運用されているGithub Actionsのymlファイルの中で、初見で何を意図した設定項目なのか不明の項目に関して以下に記載する。

## ymlファイルの各項目の簡単な解説
Github Actionsの公式ドキュメントに各設定項目の詳細な説明が網羅されているので、設定を行う際には公式ドキュメントの方を参照していただければと思いますが、今回使用した設定項目の解説を以下に列挙していきたいと思います。

### 特定のイベント発生時に当設定ファイルに記載されている処理を実行する
monorepo構成のリポジトリの場合、リポジトリの全ソースコードの中で特定のディレクトリにて変更があった場合に限定してテストを実行したいということがあると思います。
その場合には、以下の設定を追加しておくと、指定したpathのソースコードがGithubにpushされた場合のみ設定ファイル何のCI処理を実行することができます。

```yml
on:
  push:
    paths:
      - "src/backend/**"
 ```

### CIコンテナ内部でコマンドを実行する際のワーキングディレクトリを指定する
monorepo構成のリポジトリの場合、ルートディレクトリでテストを実行するのではなく、ルートディレクトリよりも深い特定の階層にてテストコマンドを実行したいという場合もあると思います。
その際には、以下の `working-directory` の設定を追加して、コマンドを実行する際のcurrent directoryを指定しておきましょう。

```yml
defaults:
  run:
    shell: bash
    working-directory: src/backend
```

### テスト実行時に使用されるMySQLコンテナの設定
自動テストを行う際には、DBコンテナとの接続は必須だと思うので以下の様にしてDBの設定を追加しましょう。

```yml
    services:
      mysql:
        image: mysql:5.7
        ports: ["3306:3306"]
        env:
          MYSQL_ROOT_PASSWORD: pass
          MYSQL_DATABASE: test
```

### 特定のcommitにチェックアウトを行うための設定
Github Actionsを使用する際には、以下の設定項目は必須の様です。
pushされた際の最新のcommitにチェックアウトした上でテストを行うためにも以下の設定を追加しましょう。

```yml
      - uses: actions/checkout@v3
```

### CIを実行するコンテナ内でnodeを使用するための設定処理
今回はTypescriptで書かれたソースコードのテストをJestを使用して行なったので、nodeを実行できる様に以下の設定を追加しています。

```yml
      - name: Set up Node
        uses: actions/setup-node@v3
        with:
          node-version: "16"
```

### テスト実行処理
以下の処理が実際のテスト実行処理になります。
TypescriptのORMとしてPrismaを使用しており、また、マイクロサービス間通信を行うためにgRPCを採用しているのでテスト実行前に、 `yarn proto` コマンドの実行と `yarn prisma migrate dev`を行なっています。

```yml
      - name: Run tests
        env:
          DATABASE_URL: mysql://root:pass@localhost:3306/test
        run: |
          yarn proto
          yarn prisma migrate dev
          yarn test
```