13
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GitHub Actions を用いて Pull-Request で変更されたファイル一覧を取り出す方法

Last updated at Posted at 2022-10-25

はじめに

ベースブランチと Pull-Request の Diff をとるために actions/checkout2 回実行して 変更されたファイル一覧を取り出すシンプルな方法を紹介します。この方法は fetch-depth: 0 オプションですべてのブランチ・タグを取得するよりも 3~4 倍高速です。

ワークフローのサンプル

.github/workflows/pr.yml
name: Check delta files
on: pull_request

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3 # まずこの PR のベースにチェックアウトしておくのがポイント
        with:
          ref: ${{ github.event.pull_request.base.sha }}
      - uses: actions/checkout@v3 # 次に Pull-Request の $GITHUB_SHA にチェックアウトする
      - name: delta files
        run: |
          git diff --diff-filter=AM --name-only \
            ${{ github.event.pull_request.base.sha }}..

ポイントの紹介

actions/checkoutv2 からはデフォルトで、そのイベントのトリガとなったコミット 1 つだけを fetch するようになったため、ひと工夫しないとベースブランチと Pull-Request の HEAD 間の Diff がとれません。例えば fetch-all-history-for-all-tags-and-branches で紹介されている fetch-depth: 0 ですべてのタグ・ブランチを取得して解決することは可能ですが、巨大なリポジトリの場合 fetch-depth: 0 で fetch すると 10 分近くかかることがあります。

その代わりに actions/checkoutref: オプションを活用して 2 回チェックアウトする方法を思いつきました。

# The branch, tag or SHA to checkout. When checking out the repository that
# triggered a workflow, this defaults to the reference or SHA for that event.
# Otherwise, uses the default branch.
ref: ''

今回は Pull-Request で変更されたファイル一覧を得たいので、ベースブランチと Pull-Request の HEAD の 2 つの履歴を取得して比較する必要がありました。(以下図の B と E の比較)
ベースブランチの HEAD の SHA の取得については webhook-events-and-payloads を参考にしました。

20230225-fig1.png

実行時間の差

fetch-depth: 0 オプションを使う場合と ref: を指定して 2 回チェックアウトを行う場合で、ワークフローの実行時間を比較しました。実行したリポジトリは巨大なカーネルリポジトリです。

ワークフローの差分は以下になります。

    steps:
      - uses: actions/checkout@v3
-       with:
-         fetch-depth: 0
+       with:
+         ref: ${{ github.event.pull_request.base.sha }}
+     - uses: actions/checkout@v3 # Run again to checkout GITHUB_SHA
      - name: delta files

必要最小限なコミットしか取得しない後者の方が、実行時間が 3~4 倍早いことがわかりました。

fetch-depth:0 の場合 checkout を 2 回行った場合
7m59s 2m23s

使用例

「変更されたファイル一覧」を活用する例を幾つか紹介します。
例えば変更されたファイル一つずつ対して Linter を実行する場合に利用できます。

他には、特定の拡張子のファイルが変更されたら Bot コメントを送って目立たせることもできます。

.github/workflows/pr.yml
- name: sample comment
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    URL: ${{ github.event.pull_request.html_url }}
  run: |
    git diff --diff-filter=AM --name-only \
      ${{ github.event.pull_request.base.sha }}.. \
      -- '*.md' > ./updated
    test -s ./updated || exit 0
    sed -i '1i以下の .md ファイルが変更されました。\n' ./updated
    gh pr comment -F ./updated "${URL}"

image.png

おわり

fetch-depth: 0 の実行時間が遅い巨大なリポジトリにおいて、どのように解消すればよいか模索していました。run: で煩雑なシェルスクリプトを書かなくてもシンプルに実現することができて良かったです。

13
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?