🏭

[GitHub Actions] pull_request イベントで動く workflow はどのバージョン/コミットのものが使われるのか

2023/11/24に公開

はじめに

pull_request イベントでトリガーされる workflow を、実際にプルリクエスト(PR)を open して動作させるとします。その際、workflow file はどのバージョンのものが用いられるでしょうか?

Open した PR の最新コミットのものが使われ...ません。

結論

  • PR merge branch (refs/pull/:prNumber/merge) が指す ref にある workflow file が用いられる
  • これは PR の target branch[1](eg: main branch) に PR branch を取り込んたバージョンの workflow が動くことを意味する
  • Target branch の workflow よりも PR のものが古い場合(eg: hotfix)に、古い workflow をそのまま動かしたいケースでは注意が必要

詳細

Workflow file がどのように参照されるかについて公式ドキュメントに記述があります:
https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#about-workflow-triggers

Each workflow run will use the version of the workflow that is present in the associated commit SHA or Git ref of the event. When a workflow runs, GitHub sets the GITHUB_SHA (commit SHA) and GITHUB_REF (Git ref) environment variables in the runner environment. For more information, see "Variables."

GITHUB_SHA/GITHUB_REF が指す workflow file が用いられることがわかります。

pull_request イベントの場合、これらの値がどうなるかについても記載があります:
https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request

  • GITHUB_SHA: Last merge commit on the GITHUB_REF branch
  • GITHUB_REF: PR merge branch refs/pull/:prNumber/merge

PR merge branch[2]とは、PR branch を target branch にマージした場合の結果を表す仮想的なブランチです。基本的にはマージコミットと同じ内容になると思って良いです。

そのため、「target branch に関係なく PR branch が指す workflow が純粋に動作する」と思っていると混乱することになります。例えば、PR branch の workflow が target branch のものより古い場合です[3]

例: Hotfix

「PR branch の workflow が target branch のものより古い」例として、hotfix があります。
例えば以下のようなケースです。

  • PR の open によりトリガーされる workflow X がある
  • Main branch の最新より古い A branch から hotfix branch を作成
    • Hotfix branch では X を変更しない
  • Main の X は hotfix branch のものよりかなり改修が進んでいるが、今回は事情により hotfix branch のものを動作させたい
  • Hotfix branch PR を open し、target branch を main にしたところ、何故か main の X が動作してしまう

Main が target branch になっていると、hotfix branch を main にマージしたバージョンの X が動作してしまうためこのようなことが起きます。

この場合、target branch を main ではなく A branch にすることで hotfix branch の X を動作させることができます[4]

脚注
  1. PR branch のマージ先 branch のこと ↩︎

  2. actions/checkout でも、pull_request イベントの場合 PR branch ではなく PR merge branch への checkout になります。ref: ${{ github.event.pull_request.head.ref }} のようにすると PR branch にチェックアウトすることができます。 ↩︎

  3. 日常的な開発で行うような、main に対して workflow を変更するような PR ではあたかも PR branch のものが動作しているように見えます。 ↩︎

  4. 最終的に main にマージしたい場合、main に対して Require status checks to pass before mergingを設定している場合はこれだけではマージできないため別途工夫が必要です。 ↩︎

Discussion