🚢

GitHub Actions でコードの差分があったときにジョブを実行したい

2024/11/28に公開

自己紹介

株式会社レスキューナウで レスキューWeb という危機情報を表示/配信するサービスの開発に関わっています、中本と申します。

やりたいこと

GitHub Actions で
「このディレクトリー以下が変更されたら、このジョブを実行したい」
ということをやってみました。

変更前のワークフローとジョブの構成

変更前の構成は、次のように 各環境 × バックエンド/フロントエンド というパターンになっていました。

  • 開発環境向け+バックエンドのワークフロー
  • 開発環境向け+フロントエンドのワークフロー
  • ステージング環境向け+バックエンドのワークフロー
  • ステージング環境向け+フロントエンドのワークフロー
  • 本番環境向け+バックエンドのワークフロー
  • 本番環境向け+フロントエンドのワークフロー

この構成では、「環境が合っているか?」「バックエンドか?」という気にしないといけないポイントが多い状況でした。
実際、「開発環境向けにデプロイしたいのに間違ってステージング環境にデプロイする」といった場合もありました。

変更後のワークフローとジョブの構成

変更後の構成は「どの環境向けか?」を間違いにくくするため、次のように 各環境の中にバックエンド/フロントエンド という設計にします。

  • 開発環境向けワークフロー
    • バックエンドのジョブ
    • フロントエンドのジョブ
  • ステージング環境向けワークフロー
    • バックエンドのジョブ
    • フロントエンドのジョブ
  • 本番環境向けワークフロー
    • バックエンドのジョブ
    • フロントエンドのジョブ

変更後の構成のために必要な対応

この構成のままでは、ワークフローを実行するトリガーとして on.push.paths 設定を行っても、バックエンド/フロントエンドの各ジョブがすべて実行されます。
変更があった対象ジョブだけデプロイしたいので、コードの差分検出を行えるか調べた結果 dorny/paths-filter を利用させていただきます。
https://github.com/dorny/paths-filter

各環境向けワークフローから共通処理として利用するため、 dorny/paths-filter を利用したワークフローコール作成します。
https://docs.github.com/ja/actions/sharing-automations/reusing-workflows#creating-a-reusable-workflow

作ったもの

全体の流れ

次の画像のように、各環境から変更差分を検出するための共通処理を呼び出し、その結果でデプロイするためのジョブを実行するか判断します。

開発/ステージング/本番向けに作成しましたが、開発環境向けを例に説明します。
作ったファイルは次のとおりです。

  • 各環境向けワークフローから差分検出のために呼ばれる共通処理のワークフローコール
    call.file-changes.yml
  • 開発環境向けワークフロー
    dev.yml

次に、作成した共通処理のワークフローコールと各環境向けのメインワークフローを説明します。

差分検出のために呼ばれる共通処理のワークフローコール

call.file-changes.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

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
    (デプロイ処理)

処理の流れについて

バックエンドのソースコードに変更があった場合を例に、処理の流れを説明します。

  1. [dev.yml] on.push.paths 設定による監視の結果、ワークフローの実行が始まる
  2. [dev.yml] deploy_backend ジョブを実行
  3. [dev.yml] needs: に設定した file-changes ジョブを実行
  4. [call.file-changes.yml] file-changes ジョブを実行
  5. [call.file-changes.yml] 結果を outputs で返す
  6. [dev.yml] 差分があったか if で確認
  7. [dev.yml] 差分があればデプロイする

さいごに

以上で、「コードの差分検出を行い、変更されたジョブだけ実行する」が実現できました。
何かのご参考になれば幸いです!

参考記事

https://qiita.com/yokawasa/items/6c8ab43200ed4ff09060

レスキューナウテックブログ

Discussion