GitHub Actionsで差分に対してのみ処理を行う
GitHub ActionsはGitHubのサーバー上でPull Requestに応じたアクションを行えるなど大変便利な機能です。
これにより、例えばマージ前にコードチェックや自動テストを行い、成功した場合だけマージを許可といった事が可能になります。
しかしながら、プロジェクトが大きくなってくると、プロジェクト全体に対して毎回コードチェックや自動テストを行うのは時間やコストがかかりすぎてしまいます。
PullRequestで変更されたファイルのみコードチェックや自動テストを行うようにすることでアクションの時間を短縮しコストを節約することができます。
ここではPullRequest内で変更されたファイル一覧を取得して、ファイルに対してアクションを行う方法を紹介します。
マージ前とマージ後
Pull Requestでの差分を取得する前に、ブランチをマージ前の状態で差分を取得するか、マージ後の状態で差分を取得するかを考える必要があります。
例えば新たに変更された内容についてテストを行い、テストに失敗した場合はマージ出来ないようにする場合はマージ前の差分を取得する必要があります。
一方で、マージ後の最新状態を使用しデプロイを行う場合など、他のブランチで行われた変更内容作業内容を含めて最新の状態で作業する場合はマージ後に差分を取得する必要があります。
マージ前に差分を取得する方法
マージ前に差分を取得するには、マージ先ブランチと現ブランチの差分を取得します。
actions/checkoutでマージ先ブランチと現ブランチの最新を取得します。
git diff に --name-only
をつけてブランチで変更されたファイルのリストを取得します。
ファイルのリストをtr '\n' ' '
でスペース区切りにすることでforでファイルをループしやすくしています。
name: check_before_merge
on:
pull_request:
types: [opened, synchronize]
jobs:
check_before_merge:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
name: checkout "${{ github.base_ref }}"
with:
fetch-depth: 1
ref: ${{ github.base_ref }}
- uses: actions/checkout@v4
name: checkout "${{ github.head_ref }}"
with:
fetch-depth: 1
ref: ${{ github.head_ref}}
- name: check_diff
shell: bash
run: |
files=(`git diff origin/${{ github.base_ref }} --name-only|tr '\n' ' ' `)
for file in ${files[@]}; do
echo ${file}
done
マージ後に差分を取得する方法
マージ後に差分を取得する場合、上記の方法ではすでにmainブランチにfeatureブランチの変更が取り込まれているため差分がなくなってしまいます。
そこで、マージコミット前後での変化を比較します。
この方法はマージコミットを利用するため Create a merge commit
あるいはSquasy and merge
でマージした場合に利用可能です。
name: check_after_merge
on:
push:
branches:
- 'main'
jobs:
check_after_merge:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
name: checkout
with:
fetch-depth: 2
- name: check_diff
shell: bash
run: |
files=(`git diff HEAD^ --name-only|tr '\n' ' ' `)
for file in ${files[@]}; do
echo ${file}
done
この方法の注意点はすでにマージされているため、仮に処理の途中でエラーとなってもマージされた状態となってしまいます。
エラーの場合はRevertを行うようにしたりSlackで通知を行うようにすると親切かと思います。
まとめ
今回はPull Request時に差分を取得する方法を紹介しました。
差分ファイルに応じた処理を行うことでアクションに必要な時間を省略したりコストを抑えることもできます。