はじめに
こんにちは。ニフティのIWSです。
今回は特定のファイルが変更されたらPRに警告を出すやり方について共有します。
何かの参考になれば幸いです。
背景
1つのファイルに手を加えたら、他のファイルも忘れずに変更しないといけないプロジェクトでは、変更漏れがどうしても生じてしまいます。
目検で漏れがないかの確認は大変なので、このテンプレートに変更があるPRが作成されたときに「HTMLに変更あるけど意図したやつ?」「テンプレートの変更1つにしか無いけど漏れてない?」みたいに警告するワークフローをつくってみました。
動作について
PRを作成した際にHTMLをファイルに変更があった際に、以下の画像の用にコメントをするワークフローが動作します。

コード
GitHub Actionsに以下の設定を行います。
コードの解説については以降の章でお話ししますので、説明を読みつつ、ご自身の利用用途に応じて書き換えてみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
name: Alerts you to template changes on: pull_request: types: [opened, reopened, synchronize] paths: - 'django/templates/process/*/*.htm' - 'django/templates/process/*/*.html' jobs: notify: runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: diff_check env: # PRにコメントするために必要 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # 変更されたテンプレートファイルのリストを取得 changed_file_list=($(git diff --name-only origin/${{ github.base_ref }} HEAD --relative="django/templates/process/" | sed 's|^django/templates/process/||')) # 変更されていないテンプレートファイルのリストを取得 no_change_file_list=($(comm -23 \ <(find django/templates/process/ -type f | sed 's|^django/templates/process/||' | sort) \ <(printf '%s\n' "${changed_file_list[@]}" | sort) )) # コメントの本文を作成 cat << EOF > ./body.txt :warning: プロセス画面テンプレートへの変更があります!! :warning: テンプレートの変更内容が意図したものか、変更漏れが無いかを確認してください! 変更されたテンプレート $(printf -- '- %s\n' "${changed_file_list[@]}") 変更されていないテンプレート $(printf -- '- %s\n' "${no_change_file_list[@]}") EOF # PRにコメント gh pr comment ${{ github.event.pull_request.number }} -F ./body.txt --repo ${{ github.repository }} |
コードの解説
処理の流れは以下です。
- 特定のファイルに変更があった際に発火
- 変更があったテンプレートのリストを取得
- 変更がなかったリストも取得
- 変更があったもの、なかったものをそれぞれコメント
1.特定のファイルに変更があった際に発火
paths
を使うことで指定したファイルに変更があったときだけワークフロー実行できます。サンプルコードは .html
と .htm
のファイルに変更があったときだけ発火する処理となります。
(もし paths-ignore
を使用すると、指定のファイル以外の変更があれば発火します。)
参考サイト:https://qiita.com/nacam403/items/3e2a5df5e88ba20aa76a
1 2 3 4 5 6 7 8 9 10 11 |
<code>on: pull_request: types: [opened, reopened, synchronize] paths: - '**.html' - '**.htm' # js配下のhoge_process.jsが対象 paths: - 'django/static/js/*process.js' </code> |
2. PRの差分を取得
1 2 3 |
# 変更されたテンプレートファイルのリストを取得 changed_file_list=($(git diff --name-only origin/${{ github.base_ref }} HEAD --relative="django/templates/process/" | sed 's|^django/templates/process/||')) |
git diff —name-only
で変更があったファイルを取得し、 --relative
をつかって指定Path以下のファイルの変更だけを取得し、それをsedで整形しています。(diff結果のPathの共通部分を削除しています django/templates/process/
)
sedの前に grep を入れることで対象を細かく指定できるようにもなります
1 2 3 4 5 6 7 |
# 変更されたJSファイルのリストを取得、process.jsとindex.jsのみを対象とする changed_file_list=($(\\ git diff --name-only origin/${{ github.base_ref }} HEAD --relative="django/static/js/" | \\ grep -E '(process|index)\\.js$' | \\ sed 's|^django/static/js/||' \\ )) |
3. 変更がなかったリストも取得
1 2 3 4 5 6 |
# 変更されていないテンプレートファイルのリストを取得 no_change_file_list=($(comm -23 \\ <(find django/templates/process/ -type f | sed 's|^django/templates/process/||' | sort) \\ <(printf '%s\\n' "${changed_file_list[@]}" | sort) )) |
2で出した変更ファイルリストと、同じPathの全体のファイル一覧のリストを突き合わせて変更されていないファイルのリストを作っています。
comm コマンドについては以下をご参考くださいませ。
参考サイト:https://qiita.com/hypermkt/items/f6388bf72d9b30c6d601
2の処理でgrepを入れた場合はこちらにもgrepを入れるのを忘れないでください。
1 2 3 4 5 6 7 8 9 10 11 |
# 変更されていないJSファイルのリストを取得 no_change_file_list=($(comm -23 \\ <( \\ find django/static/js/ -type f | \\ grep -E '(process|index)\\.js$' | \\ sed 's|^django/static/js/||' | \\ sort \\ ) \\ <(printf '%s\\n' "${changed_file_list[@]}" | sort) )) |
変更があったもの、なかったものをそれぞれコメント
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# コメントの本文を作成 cat << EOF > ./body.txt :warning: process.js or index.js ファイルへの変更があります!! :warning: プロセス画面JSファイルは画面ごとに複数あります。変更漏れが無いかを確認してください! 変更されたテンプレート $(printf -- '- %s\\n' "${changed_file_list[@]}") 変更されていないテンプレート $(printf -- '- %s\\n' "${no_change_file_list[@]}") EOF # PRにコメント gh pr comment ${{ github.event.pull_request.number }} -F ./body.txt --repo ${{ github.repository }} |
2,3で作ったリストを使って body.txt を作っています
printf -- '- ...
の --
はそれ以降の – をオプションとして扱わないことを意味します。
今回のケースでは、Markdownとして -
を使いたいのだけど、そのままだとオプションの -
と勘違いされてしまうことを回避するために入れています。
( -
を抜くと実際にprintf: - : invalid option
と怒られます。)
もしPRへコメントする際はghコマンドを使用してください。
WF発火したPRを ${{ github.event.pull_request.number }}
で指定し body.txtの内容をコメントしています。ただし、複数行のコメントにはテキストファイルなどで渡す必要があるので注意してください。
おわりに
今回は特定のファイルが変更されたらPRに警告を出すやり方について紹介しました。
変更漏れが多いリポジトリなどに是非活用してみてください。