GitHub Actions で差分ファイルのみ RuboCop を実行する

こんにちは @shutooike です。

GitHub Actions は実行時間の従量課金です。

コスト削減のため Pull Requet の差分ファイルのみ RuboCop を実行するようにしました。

完成版

on:
  - pull_request

env:
  GH_TOKEN: ${{ github.token }}
  GH_REPO: ${{ github.repository }}

jobs:
  rubocop: 
    steps:
      - run: |
          gh pr diff ${{ github.event.number }} --name-only |
          xargs -I {} sh -c '[ -f "{}" ] && echo "{}"' |
          xargs --no-run-if-empty bundle exec rubocop --force-exclusion

解説

  gh pr diff ${{ github.event.number }} --name-only |

まずは差分を取らないといけません。

最初は git diff を試しましたが、GitHub Actions では最小限しかローカルに落としておらず、実行時間も含めていい感じにならなかったので gh を使うようにしました。

参考: PR の差分を取得する [GitHub Actions]


  xargs -I {} sh -c '[ -f "{}" ] && echo "{}"' |

git diff は削除されたファイルをオプションで除外できるのですが、gh には無かったのでシェルスクリプトで存在するファイルのみに絞ります。

僕はシェルスクリプト苦手マンなのでChatGPT先生に作ってもらいました。


  xargs --no-run-if-empty bundle exec rubocop --force-exclusion

xargs--no-run-if-empty オプションでファイルがなければ実行しないようにしています。

最後に rubocop ですが、オプションがないと渡されたファイルが Ruby ファイル以外でも .rubocop.yml で Exclude の設定をしていても実行してしまいます。

そのため --force-exclusion をつけています。

参考: rubocop の --force-exclusion オプションは Exclude だけじゃなく Include も見てくれる - インゲージ開発者ブログ

おわりに

元々1分半ほどかかっていたのが、差分の量にもよりますが10秒未満になりました 👏

他にもいい方法があれば教えてください!