【Github】Github Actions ~ 差分ファイルを抽出する ~

■ はじめに

https://dk521123.hatenablog.com/entry/2024/08/10/115429

などで、Github Actions で Linter を実行したが、
実行対象ファイルは、拡張子だけで全体にかけていた。

できれば、プルリクエスト作成時/commit push時 には
ベースブランチからの差分ファイルを取得したい。
今回は、その方法をまとめて、書き直してみる。

目次

【1】サンプル
 例1:差分だけをTOML Lintする
 例2:差分だけをSQL Lintする
 例3:差分だけをSQL Lintする(別方法)
【2】Tips
 1)git diff コマンド
 2)git fetch コマンド
 3)github.event.pull_request.head.sha
 4)fetch-depth

【1】サンプル

例1:差分だけをTOML Lintする

https://dk521123.hatenablog.com/entry/2024/08/10/115429

のサンプルを修正する
以下のサイトの方法を参考に実装。

https://dev.classmethod.jp/articles/github-actions-get-diff-files-on-pr-events/

name: ValidateToml

on:
  push:
    # ★ブランチ絞るの重要★(Baseブランチ「develop」へのPushだとエラー発生)
    branches:
      - 'feature/**'
      - 'releases/**'
    paths:
      # TOML ファイル (.toml) をプッシュするたびに実行
      - '**.toml'
  pull_request:
    types:
      - opened
      - reopened
      - synchronize
    paths:
      - '**.toml'
env:
  base_branch: develop
jobs:
  validate-toml:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - name: "Checkout"
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      # リモートoriginにあるdevelopブランチを、それを追跡しているローカルにあるorigin/developにフェッチする
      - name: Fetch base branch
        run: git fetch origin ${base_branch}:${base_branch}
      - name: Validate TOML file
        run: |
          # Run actions using diff_files
          diff_files=$(git diff --diff-filter=ACM --name-only HEAD ${base_branch} -- "**.toml" \
            | tr "\n" " ")
          echo "# diff_files: ${diff_files}"

          # 差分でループ
          for file in ${diff_files[@]}; do
            echo ${file}
            python .github/validate_toml.py $file
          done 

例2:差分だけをSQL Lintする

https://dk521123.hatenablog.com/entry/2024/04/10/152101

のサンプルを修正する

以下のサイトの方法を参考に実装。

https://qiita.com/kenz_firespeed/items/b37a6a1a7f0aff931c7c

name: DemoForPullRequest

on:
  pull_request:
    types:
      - opened
      - reopened
      - synchronize
    paths:
      - '**.sql'
env:
  base_branch: develop
jobs:
  lint-job:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
            python-version: '3.10'
      - name: install SQLFluff
        run: 'pip install sqlfluff'
      - name: Switch to pull request branch
        uses: actions/checkout@v4
        with:
          # ★1:分岐を特定するために fetch-depth: 0 で履歴をすべて取得する必要がある
          fetch-depth: 0
      - name: Run actions using diff_files
        run: |
          # ★2:...: 分岐からの差分(ベースブランチの変更が含まれない = PR の Files changed)
          diff_files=$(git diff --diff-filter=ACM --name-only origin/${base_branch}...origin/${GITHUB_HEAD_REF} -- "sqls/**.sql" \
            | tr "\n" " ")
          echo "- diff_files: ${diff_files}"

          for file in ${diff_files}
          do
            echo "- target_file: ${file}"
            sqlfluff lint $file --dialect snowflake --format github-annotation-native
          done

例3:差分だけをSQL Lintする(別方法)

https://dk521123.hatenablog.com/entry/2024/04/10/152101

のサンプルを修正する
* 以下のサイトの方法を参考に実装。
 => 例2との主な変更点は、★部分参照。

https://zenn.dev/snowcait/articles/6d207409cb1be0

name: DemoForPullRequestV2

on:
  pull_request:
    types:
      - opened
      - reopened
      - synchronize
    paths:
      - '**.sql'
env:
  base_branch: develop
jobs:
  lint-job:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
            python-version: '3.10'
      - name: install SQLFluff
        run: 'pip install sqlfluff'
      - name: Switch to pull request branch
        uses: actions/checkout@v4
        with:
          # ★1:分岐を特定するために fetch-depth: 0 で履歴をすべて取得する必要があ
          fetch-depth: 0
      - name: Run actions using diff_files
        run: |
          # ★2:...: 分岐からの差分(ベースブランチの変更が含まれない = PR の Files changed)
          diff_files=$(git diff --diff-filter=ACM --name-only origin/${base_branch}...origin/${GITHUB_HEAD_REF} -- "sqls/**.sql" \
            | tr "\n" " ")
          echo "- diff_files: ${diff_files}"

          for file in ${diff_files}
          do
            echo "- target_file: ${file}"
            sqlfluff lint $file --dialect snowflake --format github-annotation-native
          done

【2】Tips

1)git diff コマンド

* git diff に --name-only をつけてブランチで
 変更されたファイルのリストを取得
* 削除したファイルはLinter候補として除外したいので
 --diff-filter=ACM (追加(A)、コピー(C)、変更(M))を指定する
* 詳細は、以下の関連記事を参照のこと

Git ~ git diffコマンド ~
https://dk521123.hatenablog.com/entry/2024/09/25/204514

2)git fetch コマンド

* リモートレポジトリからブランチ(とタグ)の情報を
 ローカルレポジトリに取得する
* 詳細は、以下の関連記事を参照のこと

Git ~ 基本編 / 基本コマンド ~
https://dk521123.hatenablog.com/entry/2020/10/02/000000

3)github.event.pull_request.head.sha

https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#pull_request

より抜粋
~~~~~~~~~~~~~
pull request の head ブランチへの最後のコミットのコミット ID を取得する場合は、
代わりに github.event.pull_request.head.sha を使います
~~~~~~~~~~~~~

4)fetch-depth

https://dk521123.hatenablog.com/entry/2022/06/16/151443

より抜粋
~~~~~~~~~~~~~~~~~~~~~
* 0 は、全てのブランチ・タグの全ての履歴を取得することを意味する
* Default: 1 (最新のコミットのみを取得する)
~~~~~~~~~~~~~~~~~~~~~

ex. Fetch all history for all tags and branches
https://github.com/actions/checkout?tab=readme-ov-file#fetch-all-history-for-all-tags-and-branches

- uses: actions/checkout@v4
  with:
    fetch-depth: 0

参考文献

https://dev.classmethod.jp/articles/github-actions-get-diff-files-on-pr-events/
https://qiita.com/kenz_firespeed/items/b37a6a1a7f0aff931c7c

関連記事

Github Actions ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/11/04/142835
Github Actions ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2022/06/16/151443
Github Actions ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/12/22/195715
Github Actions ~ ワークフロー制御 ~
https://dk521123.hatenablog.com/entry/2024/01/28/004128
Github Actions ~ Pythonを使うには ~
https://dk521123.hatenablog.com/entry/2024/02/04/011205
Github Actions ~ Python関連 ~
https://dk521123.hatenablog.com/entry/2022/06/21/143624
Github Actions ~ SQL Linter ~
https://dk521123.hatenablog.com/entry/2024/03/04/180308
Github Actions ~ Scala Linter ~
https://dk521123.hatenablog.com/entry/2024/04/02/002828
Github Actions ~ JSON Linter ~
https://dk521123.hatenablog.com/entry/2024/08/08/202314
Github Actions ~ YAML Linter ~
https://dk521123.hatenablog.com/entry/2024/08/09/141801
Github Actions ~ TOML Linter ~
https://dk521123.hatenablog.com/entry/2024/08/10/115429
Github Actions ~ pull_request / pull_request_target ~
https://dk521123.hatenablog.com/entry/2024/04/10/152101
Git ~ 基本編 / 基本コマンド ~
https://dk521123.hatenablog.com/entry/2020/10/02/000000
Git ~ git diffコマンド ~
https://dk521123.hatenablog.com/entry/2024/09/25/204514