💭

ローカルで通るテストがGitHub Actionsでコケてハマった

2022/12/07に公開

はじめに

弊社ではGitHub Actionsを使用してCIを構築しており、Pull Requestの作成時やpush時にコードフォーマットやテストを実行しています。
普段はうまく動いてくれているのですが、時々「ローカルではテストが通るのに、なぜかCIではコケる」という問題が起こっていました。
なんでだろうな〜と気になって調査した結果、原因がわかったのでまとめておきます。

何が起こったか

開発フロー

以下のようなフローで開発しているとします。

  1. 最新のdevelopブランチからfeatureブランチを作成
  2. featureブランチでいくつかコミット
  3. developブランチに対して、Pull Requestを作成

CIでのみテストがコケる

いつも通り開発して、Pull Requestを作成した後、CIがコケていることに気づきました。
ログを見ても自分が加えた変更とは関係なさそうなところで落ちています。
一方、ローカルではテストが通っています。
Why?🤷

developブランチに変更が加わっていたので、取り込んで再度テストを実行してみました。
するとローカルでもCIと同じエラーが起きました。
Why?🤷

原因はチェックアウトするブランチ

下記のように特に設定をせずチェックアウトしていたので、自分の作成したfeatureブランチをチェックアウトしていると思い込んでいましたが、これが誤りでした🤦

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

先述の事象から、CIではマージ先のブランチ(ここではdevelop)をマージ元のブランチ(ここではfeature)に取り込んだブランチ・コードベースでテストしているのでは🤔と考えて、GitHub Actionsのログを見ると refs/pull/<pr_number>/merge というブランチをチェックアウトしていました。

この refs/pull/<pr_number>/merge がなんぞやということですが、Pull Requestのマージ後の状態を表すGitHubが作成するブランチで、このブランチを作成することでコンフリクトしないか、正常にマージできるかを判断してるっぽいです。

pull/xxx/merge はマージ対象のブランチとマージした結果の状態を持つブランチである。

https://qiita.com/sonots/items/16df445132e704198e3e

https://stackoverflow.com/questions/63594658/git-refs-merge-vs-head-in-pull-request

また、actions/checkout のコードをみると、ref を指定しない場合は、github.context.ref が設定されるようです。

https://github.com/actions/checkout/blob/e6d535c99c374d0c3f6d8cd8086a57b43c6c700a/src/input-helper.ts#L63

そして、Pull Requestがトリガーの場合 github.context.refrefs/pull/<pr_number>/merge になるとドキュメントに記載されています。

The ref given is fully-formed, meaning that for branches the format is refs/heads/<branch_name>, for pull requests it is refs/pull/<pr_number>/merge,

つまり、Pull Requestがトリガーの場合のデフォルトのチェックアウト先は、refs/pull/<pr_number>/mergeということですね!

ちなみに、featureブランチのコードベースでテストを行いたい場合は以下のようにして、Pull Requestの HEAD コミットを ref に指定します。

- uses: actions/checkout@v2
  with:
    ref: ${{ github.event.pull_request.head.sha }}

https://github.com/actions/checkout/tree/releases/v2#checkout-pull-request-head-commit-instead-of-merge-commit

おわりに

checkoutの挙動をちゃんと理解してなかった自分が悪いんですが、デフォルトの設定が自分の感覚と違っている場合はハマりやすいな〜と思いました。
使用しているツールやライブラリのデフォルトの挙動は把握しておきたいものです。
ただ、ハマったのをきっかけに色々学べたので逆によかったかも?

BABY JOB  テックブログ

Discussion