hb-sun-3q5qSKpyXGQ-unsplash

モノレポで GitHub Actions の jest coverage report を動かす

jest coverage reportは GitHuba Actions のワークフローの1つで Jest で実行したテストのコードカバレッジをプルリクエスト上にコメントしてくれます。 この記事では yarn workspaces 使用して作成したモノレポ構築のレポジトリで jest coverage report を動かしてみます。

jest coverage report は GitHuba Actions のワークフローの 1 つで Jest で実行したテストのコードカバレッジをプルリクエスト上にコメントしてくれます。

この記事では yarn workspaces を使用して作成したモノレポ構築のレポジトリで jest coverage report を動かしてみます。

実際の構成は以下のレポジトリを参照してください。

.github/workflows の設定

モノレポのレポジトリに対するワークフローを記述したファイルは以下のとおりになります。

name: Coverage Report
on:
  pull_request:
    branches: [main]
  workflow_dispatch:
jobs:
  # マトリックス戦略を使用するために、変更された packages を取得する
  generate_matrix:
    name: Get changed packages
    runs-on: ubuntu-latest
    outputs:
      names: ${{ steps.changed_packages.outputs.names }}
      paths: ${{ steps.changed_packages.outputs.paths }}
      empty: ${{ steps.changed_packages.outputs.empty }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3
 
      - name: Find changed packages
        id: changed_packages
        uses: alexshukel/get-changed-workspaces-action@v1.0.0
  coverage:
    name: Coverage report
    # このジョブを実行するためには generate_matrix が正常に完了している必要がある
    needs: [generate_matrix]
    if: ${{ !fromJson(needs.generate_matrix.outputs.empty) }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        # 変更された packages をマトリックス戦略に渡す
        path: ${{ fromJson(needs.generate_matrix.outputs.paths) }}
    steps:
      - uses: actions/checkout@v3
 
      - name: Use Node
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: yarn
 
      - name: Installing dependencies
        run: yarn install
 
      - uses: artiomtr/jest-coverage-report-action@v2
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          # モノレポのルートで install してるのでそれぞれのディレクトリではインストール不要
          skip-step: install
          # ワークフローを実行するディレクトリを指定する
          working-directory: ${{ matrix.path }}
          test-script: yarn test
          package-manager: yarn
 

各ステップごとに細かく見てきましょう。

変更されたファイルを検出する

generate_matrix ジョブでは GitHub Actions のマトリックス戦略 を使用するために必要なデータを取得します。マトリックス戦略を使用すると変数を用いて、変数の組み居合わせに基づいて複数のジョブを作成できます。

例えば、以下のようにモノレポのパッケージの一覧のパスを変数として宣言しておくことで、パッケージごとにジョブを実行できます。

jobs:
  coverage:
    strategy:
      matrix:
        path:
          - ./packages/front
          - ./packages/server

しかし、上記のようにマトリックスの変数をハードコーディングしていると、新たにパッケージを追加したときに修正を忘れる可能性があります。なによりファイルが変更されているかどうかに関わらず、すべてのテストが実行されてしまいます。モノレポ構成のレポジトリで GitHub Actions を実行する場合、変更のないディレクトリに対する無駄な実行は避けたいところでしょう。

そこで、generate_matrix ジョブ変更されたモノレポのパッケージの一覧を取得して、その値を後続のジョブでマトリックスの変数として使用できるように準備を行います。

モノレポのパッケージが変更されたかどうか取得するために Get changed workspaces action ワークフローを使用します。このワークフローは workspaces@ の中で変更されたファイルを検出して以下のような JSON で outputs` として出力してくれます。

[{"name":"@monorepo/core","path":"packages/core"},{"name":"@monorepo/react","path":"packages/react"}]

outputs キーでは後続のジョブで使える値をマップ形式で定義しています。Get changed workspaces action ワークフローで出力された値を後続のジョブで使用できるようにしています。

outputs:
  names: ${{ steps.changed_packages.outputs.names }}
  paths: ${{ steps.changed_packages.outputs.paths }}
  empty: ${{ steps.changed_packages.outputs.empty }}

テストの実行

それでは前述のジョブで取得した値をもとにテストを実行してカバレッジを取得します。neets キーはこのジョブを実行する間に正常に完了するジョブを文字列または文字列の配列で指定します。今回の例では coverage ジョブが generate_matrix ジョブに依存していることを示しています。

needs: [generate_matrix]

if キーは条件文を使って条件を満たした場合のみジョブが実行されるようにします。needs.generate_matrix.outputs.empty は前の generate_matrix ジョブから取得した値で true の場合には workspaces のパッケージの中で変更されたファイルが存在しないことを示しています。fromJSON は GitHub Actions で使用できる式であり、 JSON オブジェクトから値を取得します。

if: ${{ !fromJson(needs.generate_matrix.outputs.empty) }}

前のジョブで説明したとおり、マトリックス戦略で変更されたパッケージのみテストされるようにしています。

strategy:
  matrix:
    # 変更された packages をマトリックス戦略に渡す
    path: ${{ fromJson(needs.generate_matrix.outputs.paths) }}

jest coverage report はデフォルトの設定では npm/yarn によるパッケージのインストールまで実行してくれるのですが、モノレポ構成の場合には各ディレクトリでパッケージをインストールするのではなく、ルートディレクトリでパッケージをインストールするのが一般的です。そのため、個別のステップで yarn install を実行しています。

- name: Installing dependencies
  run: yarn install

さらに、jest coverage report ワークフローを使用する際にもいくつかのオプションを設定しています。

- uses: artiomtr/jest-coverage-report-action@v2
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    skip-step: install
    working-directory: ${{ matrix.path }}
    test-script: yarn test
    package-manager: yarn

ルートディレクトリで yarn install を実行しているので skip-step: install を指定してそれぞれのディレクトリではパッケージのインストールを実行しないようにしています。working-directory ではテストを実行するディレクトリを指定しています。この値はマトリックス戦略で定義した変数から取得するので matrix.path のように matrix コンテキストから取得しています。

GitHub Actions の実行

これでワークフローの準備は整いました。実際にプルリクエストを作成してみると、変更の合ったファイルに対してのみカバレッジレポートが出力されていることがわかります。

スクリーンショット 2022-11-27 18.13.44

スクリーンショット 2022-11-27 18.15.48

参考

Monorepo or yarnWorkspaces support? #260


Contributors

> GitHub で修正を提案する
この記事をシェアする
はてなブックマークに追加

関連記事