モノレポで GitHub Actions を使って自動テストする👼

# やりたいこと

以下のようなモノレポの構成のリポジトリがありました。

```
.
├── package.json
└── packages
    ├── a
    │   └── package.json
    └── b
        └── package.json
```

😥 自動テストしたいよ〜
😥 修正があったパッケージだけ自動テストしたいよ〜

👼 できるよ

😥 ?!

ということで、簡単にできる方法があるのでご紹介します 🎉

サンプルコードは以下になります。

https://github.com/miyukikoga/monorepo-test-actions-sample

# やること一覧

- workspace を設定する
- ワークフローを作る
-  GitHub Actions を実行する

# workspace を設定する

npm workspace 機能を使うことで、単一のルートパッケージから複数のパッケージを workspace として管理することができます。
既存のパッケージは package.json に以下の設定を追加すれば大丈夫です。

```package.json
  "name": "",
  ...
  "private": true,
  "workspaces": [
    "packages/a",
    "packages/b"
  ],
  ...
```

新しく作る場合は以下のようにパッケージを作成します。

```
$ npm init -w packages/c
```

# ワークフローを作る

完成形はこちら。
[get-changed-workspaces-action](https://github.com/AlexShukel/get-changed-workspaces-action) を使って変更された workspace を検出しています。

```.github/workflows/test.yaml
name: Monorepo Test Actions Sample

on: [pull_request]

jobs:
  get-changed-workspaces:
    runs-on: ubuntu-latest
    outputs:
      packages: ${{ steps.changed-packages.outputs.packages }}
      empty: ${{ steps.changed-packages.outputs.empty }}
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Find changed workspaces
        uses: AlexShukel/get-changed-workspaces-action@v2.0.0
        id: changed-packages

  test-jest:
    name: Test with Jest
    # get-changed-workspaces が正常に完了した時、このジョブは実行されます
    needs: [get-changed-workspaces]
    # workspace に変更がなければこのジョブをスキップします
    if: ${{ !fromJson(needs.get-changed-workspaces.outputs.empty) }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        # 変更された packages をマトリックスに渡す
        package: ${{ fromJson(needs.get-changed-workspaces.outputs.packages) }}
    steps:
      - uses: actions/checkout@v3
      - name: Test
        run: npm run test
        working-directory: ${{ matrix.package.path }}
```

重要な箇所をかいつまんで説明します。

### 変更された workspaces を検出する

以下で変更された workspaces を検出しています。
get-changed-workspaces-action の詳細は [こちら](https://github.com/AlexShukel/get-changed-workspaces-action) で確認することができます。

```
      - name: Find changed workspaces
        uses: AlexShukel/get-changed-workspaces-action@v2.0.0
        id: changed-packages
```

test-jest に検出した情報を渡します。

```
    outputs:
      packages: ${{ steps.changed-packages.outputs.packages }}
      empty: ${{ steps.changed-packages.outputs.empty }}
```

### 変更された workspaces でテストを実行する

test-jest を実行するには get-changed-workspaces が正常に完了している必要があるので needs を設定します。

```
    needs: [get-changed-workspaces]
```

workspace に変更がなければ test-jest をスキップします。

```
    if: ${{ !fromJson(needs.get-changed-workspaces.outputs.empty) }}
```

変更された workspaces をマトリックスに渡します。
マトリックスの詳細については [こちら](https://docs.github.com/ja/actions/using-jobs/using-a-matrix-for-your-jobs) を参照ください。

```
    strategy:
      matrix:
        # 変更された packages をマトリックスに渡す
        package: ${{ fromJson(needs.get-changed-workspaces.outputs.packages) }}
```

変更された workspaces に移動して `npm run test` を実行します。
matrix.package.path には `/home/runner/work/${リポジトリ名}/${リポジトリ名}/packages/a` のような値が入っています。

```
      - name: Test
        run: npm run test
        working-directory: ${{ matrix.package.path }}
```

これでワークフローは完成です 🙌

# GitHub Actions を実行する

プルリクエストを作ってテストが実行されているか確認しましょう！

![スクリーンショット 2023-02-01 8.03.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71897/ddc112d1-9d51-261b-82a5-8ff3373b5395.png)


# 感想

意外と簡単にできましたね 🤗
テストだけじゃなくてデプロイにも使えるので good です 👍

# 参考

https://qiita.com/frozenbonito/items/8230d4a3cb5ea1b32802

https://azukiazusa.dev/blog/monorepo-github-actions-jest-coverage-report-action/