GitHub Actions の github.event.pull_request.base.sha の使いどろこが難しい
GitHub Actions の pull_request
トリガー時に取得できるイベントの値として github.event.pull_request.base.sha
がある。
以前 プルリク前後の apk ファイルを比較する GitHub Actions に書いたように、プルリク前後の何かしらの比較で利用できると思っていたが、これを利用することに次のような問題があることに最近、気づいた。
- あくまでプルリクの向き先(base)の commit SHA なので、実際の運用ではプルリクの基点とした(プルリク用のブランチを切る基とした)ブランチへのプルリクが行われるとは限らない
- 仮に、常にプルリクの基点としたブランチに対してプルリクを作る運用としても、ブランチを切ってからプルリクを作成するまでに、(他の開発者によって)base のブランチのコミットが進んでしまっている可能性がある
-
github.event.pull_request.base.sha
の値はこの進んでしまった commmit SHA となる
-
- プルリク作成後に、base のブランチのコミットが進んでも
github.event.pull_request.base.sha
の値は更新されずプルリク作成時のまま- GitHub のバグ?
上の2つはまあそうだよねという話であるが、3つ目のバグ?があるのでワークフローで利用するのは厳しい。よってプルリク前後で何かしらの比較をしたければ
- 変更前:
github.base_ref
- 変更後:
github.sha
で比較した方がよい。この場合 github.sha
のコードはプルリクのブランチのコード(開発者の手元のコード)とは異なり、「マージ後にそうなるであろうコード」となる。下記は参考記事。
尚、github.base_ref
は commit SHA でなくブランチ名であるので、仮に処理時間の長いワークフローを動かす場合に(他の開発者によって)base のブランチのコミットが進む可能性があるので、処理の内容次第だが一貫性が無く困る場合は処理の最初の方でブランチ名から commit SHA を取得しておいてそれを利用するようにした方がよい。
他には、base との比較せずに、プルリクのファーストコミットの一つ前のコミットと比較する方法があるが、その場合の実装は下記を参考にされたし。
上記の実装で、初めはプルリクの最終コミットの SHA(github.event.pull_request.head.sha
)からプルリクのコミット数(github.event.pull_request.commits
)の数だけ遡ればよいと思ったが、マージコミットが含まれる場合に面倒そうだったのでその方法は採用しなかった。尚、github.event.after
も github.event.pull_request.head.sha
と同じ値となるが、これはプルリクの open 時には取得できないので注意。
補足:比較でなくプルリクの静的解析や成果物のビルド等の場合
上記にも書いた通り、github.sha
は「マージ後にそうなるであろうコード」である。GitHub Actions のワークフローにおいてコードをチェックアウトする場合は actions/checkout を使うことが多いと思うが、この action で ref
を指定しない場合、デフォルトではそのコードがチェックアウトされる。
目的の処理が「マージ後にそうなるであろうコード」の方が相応しければそれでよいのだが、もしプルリクのブランチのコード(開発者の手元のコードと同じコード)に対して静的解析なりビルドなりしたいんだよという場合は ref
に github.event.pull_request.head.sha
を指定する。
目的の処理に応じてどちらを採用するかを決めればよいが、前者の場合、開発者の手元では問題ないのに CI が通らない(例えば base ブランチの不具合を取り込んでしまった上での静的解析)ということが起こりうるので、どちらを採用しているのか開発者が理解しておくことが大事である。
また、リポジトリの設定で次のような項目があるので、設定の有効化を検討されたし。
- リポジトリの設定
- リポリポジトリの Rulesets の設定
Discussion