🐙

GitHub Actions workflows で Pull Request の差分コミットだけ fetch する

2023/09/10に公開

Pull Request の diff から何かを確認したいときや、Pull Request に含まれるコミットそれぞれをチェックしたい場合、Pull Request の base (例えば main) からその Pull Request の最新コミットまでを含む履歴が必要になります。このとき、リポジトリすべての履歴ではなく、必要な履歴のみを取得すると CI の高速化が可能です。

GitHub Actions workflows の actions/checkout はデフォルトで fetch-depth1 に設定されていて最新のコミットのみを取得するようになっています。Pull Request に複数コミットが含まれる場合、これでは base との diff はとれません。fetch-depth0 に設定するとすべての履歴を取得できますが、巨大なリポジトリでは時間がかかります。

Pull Request でトリガーされる workflow の場合、GitHub contextevent プロパティに pull_requet オブジェクトが含まれています。次のようにするとベースからの履歴のみを取得できます。

- run: echo "fetch_depth=$(( commits + 1 ))" >> $GITHUB_ENV
  env:
    commits: ${{ github.event.pull_request.commits }}
- uses: actions/checkout@v4
  with:
    fetch-depth: ${{ env.fetch_depth }}

github.even.pull_request.commits で Pull Request に含まれるコミット数が取得できます。ベースを含めるために + 1 する必要があり環境変数を経由しています。

例えば Pull Request に含まれるコミットすべてが Conventional Commits を満たしているかチェックする workflow は次のようになります。

name: Conventional Commits

on: [pull_request]

jobs:
  commitlint:
    runs-on: ubuntu-latest
    steps:

      # fetch-depth の計算
      - run: echo "fetch_depth=$(( commits + 1 ))" >> $GITHUB_ENV
        env:
          commits: ${{ github.event.pull_request.commits }}

      # 必要な履歴だけを fetch
      - uses: actions/checkout@v4
        with:
          fetch-depth: ${{ env.fetch_depth }}

      # Conventional Cmmits のチェック
      - uses: actions/setup-node@v3
      - run: npm install -g @commitlint/cli @commitlint/config-conventional
      - run: npx commitlint --from "$from" --to "$to" --verbose -x "$extends"
        env:
          from: ${{ github.event.pull_request.base.sha }}
          to: ${{ github.event.pull_request.head.sha }}
          extends: "@commitlint/config-conventional"

おまけ

kubernetes/kubernetes リポジトリ (118,324 コミット) で試した結果次のようになりました。

fetch-depth Job 実行時間
0 2m 8s
1 18s
10 21s
name: fetch-deth comparison

on: [pull_request]

jobs:
  depth0:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          repository: kubernetes/kubernetes
          fetch-depth: 0

  depth1:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          repository: kubernetes/kubernetes
          fetch-depth: 1

  depth10:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          repository: kubernetes/kubernetes
          fetch-depth: 10
GitHubで編集を提案

Discussion