paths-filter を使ってワークフローのジョブをスキップする
マージ前にベースブランチの変更の取り込みを必須化
手ぶら登園 では GitHub を使って開発を行っており、品質向上のために、マージ前にベースブランチの変更の取り込みを必須化しました。
必須化の経緯や方法等はアドベントカレンダーの 12 日目の記事で書いているので、気になった方はご覧ください。
CI には GitHub Actions を使っていて、主にバックエンドのテストを行っているので、マージ前にベースブランチの変更の取り込みを必須化する際のステータスチェックとしてもテストを選択しました。「ベースブランチの変更を取り込み済み」かつ「テストが通っている」ならばマージできるという設定です。
マージできなくなる問題
ドキュメント系の変更や HTML や CSS のみの変更の場合に、バックエンドのテストは不要です。
そのため、CI の実行時間の節約や開発体験を考慮して paths-ignore によって、特定のケースでワークフローを起動しない設定にしていました。
on:
push:
branches: [develop, main]
paths-ignore:
- 'ignore-path1/**'
- 'ignore-path2/**'
pull_request:
branches: ["**"]
paths-ignore:
- 'ignore-path1/**'
- 'ignore-path2/**'
この状態で前述の「ベースブランチの変更を取り込み済み」かつ「テストが通っている」ならばマージできるという設定をしました。すると、paths-ignore にマッチした場合に、ワークフローが起動しないので、結果としてステータスチェックをパスできずにマージできなくなる問題が起こりました。
ワークフローは実行しつつも、ジョブをスキップする
ワークフローレベルでスキップするのではなく、ジョブレベルでスキップすれば、ステータスチェックも通ります。そのため、解決策としては paths-ignore と同等のことをテストジョブの if でやればいいわけです。
既存の if に paths-ignore と同等の制御を加えると、条件が複雑になって可読性が悪いので、paths-filter を使いました。
paths-filter はワークフロー組み込みの paths と似たことをジョブレベル、ステップレベルでできるようにするライブラリです。
README を見ながら、以下のように設定するとシンプルな記述でジョブの実行制御ができるようになり、マージできない問題も解消しました!
on:
push:
branches: [develop, main]
pull_request:
branches: ["**"]
jobs:
need-ci:
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
paths: ${{ steps.filter.outputs.paths }}
permissions:
pull-requests: read
contents: read
steps:
- name: Checkout
if: github.event_name == 'push'
uses: actions/checkout@v4
- name: Filter paths
uses: dorny/paths-filter@v2
id: filter
with:
base: ${{ github.ref }}
# paths-ignore の代わりとして使うので、test を実行したいファイルのみをピックアップする
# 変更したファイルがいずれかにマッチすれば true
filters: |
paths:
- 'test-required-path1'
- 'test-required-path2/**'
test:
runs-on: ubuntu-latest
timeout-minutes: 10
needs:
- need-ci
if: (!failure()) && (needs.need-ci.outputs.paths == 'true')
steps:
- name: Checkout
if: github.event_name == 'push'
uses: actions/checkout@v4
# 以下省略
私たち BABY JOB は、子育てを取り巻く社会のあり方を変え、「すべての人が子育てを楽しいと思える社会」の実現を目指すスタートアップ企業です。圧倒的なぬくもりと当事者意識をもって、こどもと向き合う時間、そして心のゆとりが生まれるサービスを創出します。baby-job.co.jp/
Discussion