ローカルで通るテストがGitHub Actionsでコケてハマった
はじめに
弊社ではGitHub Actionsを使用してCIを構築しており、Pull Requestの作成時やpush時にコードフォーマットやテストを実行しています。
普段はうまく動いてくれているのですが、時々「ローカルではテストが通るのに、なぜかCIではコケる」という問題が起こっていました。
なんでだろうな〜と気になって調査した結果、原因がわかったのでまとめておきます。
何が起こったか
開発フロー
以下のようなフローで開発しているとします。
- 最新のdevelopブランチからfeatureブランチを作成
- featureブランチでいくつかコミット
- 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 はマージ対象のブランチとマージした結果の状態を持つブランチである。
また、actions/checkout
のコードをみると、ref
を指定しない場合は、github.context.ref
が設定されるようです。
そして、Pull Requestがトリガーの場合 github.context.ref
は refs/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 isrefs/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 }}
おわりに
checkoutの挙動をちゃんと理解してなかった自分が悪いんですが、デフォルトの設定が自分の感覚と違っている場合はハマりやすいな〜と思いました。
使用しているツールやライブラリのデフォルトの挙動は把握しておきたいものです。
ただ、ハマったのをきっかけに色々学べたので逆によかったかも?
私たち BABY JOB は、子育てを取り巻く社会のあり方を変え、「すべての人が子育てを楽しいと思える社会」の実現を目指すスタートアップ企業です。圧倒的なぬくもりと当事者意識をもって、こどもと向き合う時間、そして心のゆとりが生まれるサービスを創出します。baby-job.co.jp/
Discussion