ChromaticをプルリクのCIで必須条件にする方法(+モノレポでの運用)
今回は、モノレポにおけるChromaticのCI設定について、効率化のためのテクニックを紹介します。記事内では詳細な手順は割愛し、ポイントを押さえた概要をお伝えします。(雰囲気は記事だけでわかると思います!)
モノレポでの課題と解決策
モノレポで開発を行う場合、特定のアプリに変更があったときに、他のアプリまで無駄にChromaticのビルドが走ってしまうことがあります。これはCIの効率を低下させ、コストも増加する原因になります。このような問題を避けるため、変更のあったアプリだけにChromaticのビルドを適用する方法を紹介します。
具体的には、tj-actions/changed-filesというGitHub Actionsのアクションを活用します。このアクションを使うことで、特定のファイル群に変更があったときにだけ、特定のActionを走らせることができるようになります。
以下、公式ドキュメントから引用した設定例です。
jobs:
changed-files:
runs-on: ubuntu-latest
name: changed-files
outputs:
all_changed_files: ${{ steps.changed-files.outputs.all_changed_files }}
# 対象ファイルに変更があったかどうかがわかる判定
any_changed: ${{ steps.changed-files.outputs.any_changed }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
# app/配下または.storybook/配下に変更があるかどうかチェック
files: |
app/**
.storybook/**
chromatic:
name: Run visual tests
needs: [changed-files]
# 何か変更があればJobを走らせる
if: ${{ needs.changed-files.outputs.any_changed == 'true' }}
uses: ./.github/workflows/chromatic.yml
secrets: inherit
この設定により、例えばApp Aに変更があった場合にはApp Aだけのビルドが走り、App Bには影響を与えないようにできます。
(実際の設定例は このあたり から話しています)
変更のない場合でもCIを通す方法
通常、CIのパイプラインでは特定のチェックが通らないとマージができないように設定したいことが多いです。そこでGitHubではPRの際に ステータスチェック を実施することができます。「あるCIが通らないとマージができない」というようにチェックを強制することができるのです。この機能を使うと、「必ずChromaticがApproveされていないとマージができない」という堅牢な仕組みが導入できます。
しかし、現状(執筆時点)はGitHubの仕様上、この設定には罠があります。文字通り、PRの際に「必ずChromaticがApproveされていないとマージができない」のです。
何が問題なのかと言うと、例えばフロントエンドでしかChromaticのCIが走らないようにしているときに、バックエンドのコードだけ修正したとします。そしてPRを出したときに、効率のことを考えて Chromaticが走らないようにする のが比較的多いかと思います。この場合、GitHubとしては 「Chromaticのチェックが通っている」と認識できない ため、PRがマージできなくなる、という問題が発生してしまいます。この問題への対処法に長年苦しめられています...(誰か良い方法知っていたら教えて下さい...)
これに対する解決策として、Chromaticが提供する "skip" の機能が役に立ちます。
chromatic-approve:
name: Run Chromatic and Approve
needs: [changed-files]
# 興味のあるファイルに何も変更が無いのであればこのJobを走らせる
if: ${{ needs.changed-files.outputs.any_changed == 'false' }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
# 問答無用にskipさせることで、CIのチェックを通すことができる
skip: "*"
この機能を利用すると、変更がなかった場合でもChromaticのジョブを自動的にパスしたことにすることができます。これにより、不要なビルドをスキップしつつ、マージのために必要な条件を満たすことが可能になります。
この部分の設定については、 動画のこのあたり で実際に設定しているので、気になる人は見てみてください。
最終的にWorkflowは以下のような形になります
name: "Chromatic"
on: push
jobs:
changed-files:
runs-on: ubuntu-latest
name: changed-files
outputs:
all_changed_files: ${{ steps.changed-files.outputs.all_changed_files }}
any_changed: ${{ steps.changed-files.outputs.any_changed }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files: |
src/**
.storybook/**
chromatic:
name: Run Chromatic
needs: [changed-files]
if: ${{ needs.changed-files.outputs.any_changed == 'true' }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
onlyChanged: true
chromatic-approve:
name: Run Chromatic and Approve
needs: [changed-files]
if: ${{ needs.changed-files.outputs.any_changed == 'false' }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
skip: "*"
まとめ
今回のテクニックは、モノレポ環境でのCI効率化に役に立つかと思います!(コストを下げつつ・CIの効率もUPします)。また、Chromaticに限らずGitHub Actionsの他のワークフロー(例えばフロントエンドとバックエンドでCIを分けている場合など)でも応用が可能なので、ぜひ活用してみてください。
Discussion