GitHub Actions でコードの差分があったときにジョブを実行したい
自己紹介
株式会社レスキューナウで レスキューWeb という危機情報を表示/配信するサービスの開発に関わっています、中本と申します。
やりたいこと
GitHub Actions で
「このディレクトリー以下が変更されたら、このジョブを実行したい」
ということをやってみました。
変更前のワークフローとジョブの構成
変更前の構成は、次のように 各環境 × バックエンド/フロントエンド というパターンになっていました。
- 開発環境向け+バックエンドのワークフロー
- 開発環境向け+フロントエンドのワークフロー
- ステージング環境向け+バックエンドのワークフロー
- ステージング環境向け+フロントエンドのワークフロー
- 本番環境向け+バックエンドのワークフロー
- 本番環境向け+フロントエンドのワークフロー
この構成では、「環境が合っているか?」「バックエンドか?」という気にしないといけないポイントが多い状況でした。
実際、「開発環境向けにデプロイしたいのに間違ってステージング環境にデプロイする」といった場合もありました。
変更後のワークフローとジョブの構成
変更後の構成は「どの環境向けか?」を間違いにくくするため、次のように 各環境の中にバックエンド/フロントエンド という設計にします。
- 開発環境向けワークフロー
- バックエンドのジョブ
- フロントエンドのジョブ
- ステージング環境向けワークフロー
- バックエンドのジョブ
- フロントエンドのジョブ
- 本番環境向けワークフロー
- バックエンドのジョブ
- フロントエンドのジョブ
変更後の構成のために必要な対応
この構成のままでは、ワークフローを実行するトリガーとして on.push.paths
設定を行っても、バックエンド/フロントエンドの各ジョブがすべて実行されます。
変更があった対象ジョブだけデプロイしたいので、コードの差分検出を行えるか調べた結果 dorny/paths-filter
を利用させていただきます。
各環境向けワークフローから共通処理として利用するため、 dorny/paths-filter
を利用したワークフローコール作成します。
作ったもの
全体の流れ
次の画像のように、各環境から変更差分を検出するための共通処理を呼び出し、その結果でデプロイするためのジョブを実行するか判断します。
開発/ステージング/本番向けに作成しましたが、開発環境向けを例に説明します。
作ったファイルは次のとおりです。
- 各環境向けワークフローから差分検出のために呼ばれる共通処理のワークフローコール
call.file-changes.yml
- 開発環境向けワークフロー
dev.yml
次に、作成した共通処理のワークフローコールと各環境向けのメインワークフローを説明します。
差分検出のために呼ばれる共通処理のワークフローコール
name: Detect changes for source codes
on:
workflow_call:
outputs:
backend:
value: ${{ jobs.file-changes.outputs.backend }}
frontend:
value: ${{ jobs.file-changes.outputs.frontend }}
jobs:
file-changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
backend:
- 'backend/**'
frontend:
- 'frontend/**'
outputs:
backend: ${{ steps.filter.outputs.backend }}
frontend: ${{ steps.filter.outputs.frontend }}
dev.yml
開発環境向けワークフロー name: "Development"
on:
push:
branches:
- develop
paths:
# パスを変更するさいは call.file-changes.yml も変更する
- 'backend/**'
- 'frontend/**'
jobs:
file-changes:
uses: ./.github/workflows/call.file-changes.yml
deploy_backend:
name: "Deploy 'Backend'"
needs: file-changes
if: needs.file-changes.outputs.backend == 'true'
runs-on: ubuntu-latest
(デプロイ処理)
deploy_frontend:
name: "Deploy 'Frontend'"
needs: file-changes
if: needs.file-changes.outputs.frontend == 'true'
runs-on: ubuntu-latest
(デプロイ処理)
処理の流れについて
バックエンドのソースコードに変更があった場合を例に、処理の流れを説明します。
-
[dev.yml]
on.push.paths
設定による監視の結果、ワークフローの実行が始まる -
[dev.yml]
deploy_backend
ジョブを実行 -
[dev.yml]
needs:
に設定したfile-changes
ジョブを実行 -
[call.file-changes.yml]
file-changes
ジョブを実行 -
[call.file-changes.yml] 結果を
outputs
で返す -
[dev.yml] 差分があったか
if
で確認 - [dev.yml] 差分があればデプロイする
さいごに
以上で、「コードの差分検出を行い、変更されたジョブだけ実行する」が実現できました。
何かのご参考になれば幸いです!
参考記事
Discussion