
# 変更されたパスのみをテストするモノレポ

実行のたびに、すべてのアプリでカバレッジを実行し、すべてのレポートをアップロードします。これがシンプルな構成です。テストの実行とアップロードがそれぞれ1回で済み、アプリの追加、名前変更、削除があっても正しく動作し続けます。古いレポートの保管場所を管理する必要もありません。

{% hint style="warning" %}
各アップロードは、そのリポジトリとブランチのカバレッジを置き換えます。Aikido は前回のアップロードとマージしません。変更されたアプリのみをアップロードすると、それ以外のすべてのアプリは、後のアップロードで再び含まれるまで Code Coverage から削除されます。
{% endhint %}

変更のないアプリのテストをスキップするのは、パイプラインを高速化するための最適化です。それでもアップロードにはすべてのアプリを含める必要があります。実行しなかった各アプリの最新レポートを保持し、実行したアプリのレポートと一緒に送信してください。

## 変更のないアプリをスキップする

この最適化を使う場合は、アプリごとに1つのアーティファクトを保持し、実行のたびにそれらすべてをアップロードします。

1. アプリのパスが変更された場合は、そのテストを実行し、レポートを `coverage-web` のような独自のアーティファクトとして公開します。
2. アプリのパスが変更されていない場合は、最後に成功した実行からそのアプリのアーティファクトをダウンロードし、同じレポートを再度公開します。再公開するとアーティファクトの保持期間が更新されるため、めったに変更されないアプリが、前のアーティファクトの期限切れによって削除されることはありません。
3. 最後のジョブで、この実行のすべてのアプリのアーティファクトをダウンロードし、すべてのレポートパスを1回のアップロードで渡します。2回目のアップロードは1回目を置き換えます。

{% hint style="warning" %}
変更のないアプリのスキップを始める前に、main ブランチですべてのアプリのカバレッジを一度実行してください。アップロードステップはすべてのアプリのレポートを想定しているため、それらのアーティファクトが main に存在するまでジョブは失敗します。
{% endhint %}

## GitHub Actions

{% code title=".github/workflows/coverage.yml" overflow="wrap" %}
```yaml
name: Coverage

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        app: [web, api]
    permissions:
      contents: read
      actions: read
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Did this app change?
        id: changes
        run: |
          if git diff --name-only "${{ github.event.before }}" "${{ github.sha }}" | grep -q "^apps/${{ matrix.app }}/"; then
            echo "changed=true" >> "$GITHUB_OUTPUT"
          else
            echo "changed=false" >> "$GITHUB_OUTPUT"
          fi

      - name: Test the app that changed
        if: steps.changes.outputs.changed == 'true'
        run: npm test --workspace=apps/${{ matrix.app }} -- --coverage

      - name: Reuse the latest available report when nothing changed
        if: steps.changes.outputs.changed == 'false'
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          mkdir -p "apps/${{ matrix.app }}/coverage"
          run_id=$(gh run list --workflow coverage.yml --branch main --status success --limit 1 --json databaseId --jq '.[0].databaseId')
          gh run download "$run_id" --name "coverage-${{ matrix.app }}" --dir "apps/${{ matrix.app }}/coverage"

      - uses: actions/upload-artifact@v4
        with:
          name: coverage-${{ matrix.app }}
          path: apps/${{ matrix.app }}/coverage/lcov.info

  upload-coverage:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      actions: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4
        with:
          pattern: coverage-*
          path: coverage-reports

      - uses: AikidoSec/code-coverage-github-action@latest
        with:
          file-paths: |
            coverage-reports/coverage-web/lcov.info
            coverage-reports/coverage-api/lcov.info
```
{% endcode %}

各テストジョブは、新しい `lcov.info` を作成するか、main に保存されたものをダウンロードします。アップロードジョブは両方を送信します。`actions/download-artifact` は、各アーティファクトを同じ名前のフォルダに配置します。

ワークフローファイルの名前は `coverage.yml` にしてください。プルリクエストでは、`main` から保存済みのレポートをダウンロードします。プルリクエストのブランチには、復元元となる以前の実行がないためです。

## その他の CI プラットフォーム

GitLab CI、Bitbucket Pipelines、Azure DevOps でも同じ最適化を使用できます。各アプリのレポートを公開し、このパイプラインで再生成しなかったレポートを復元して、すべてのレポートをまとめてアップロードします。各プラットフォームのアップロードステップについては、[カバレッジレポートをアップロードする](https://help.aikido.dev/docs/docs-ja/code-quality/code-coverage#upload-a-coverage-report)を参照してください。

## 関連

{% content-ref url="./" %}
[.](https://help.aikido.dev/docs/docs-ja/code-quality/code-coverage)
{% endcontent-ref %}

{% content-ref url="pr-gating-on-code-coverage.md" %}
[pr-gating-on-code-coverage.md](https://help.aikido.dev/docs/docs-ja/code-quality/code-coverage/pr-gating-on-code-coverage)
{% endcontent-ref %}
