くりにっき

フルスタックキュアエンジニアです

mainブランチよりも古いブランチでCIを実行できなくしたい

たまにやりたくなるやつメモ

モチベーション

CIでTerraformを動かしていると

  • mainブランチを自動apply
  • PRとかでマージ前に挙動を確認したい場合はPRに出ているブランチを手動apply

というワークフローを作ることがよくあるんですが、最新のmainブランチよりも古いブランチをapplyした時にapply済の構成が巻き戻って事故になるため、そうならないように防止したかったというやつです。

実際のスクリプト

どのCIで動かすかによって多少は変わってくると思うけどだいたいこれで動くと思います。

default_branch=`git remote show origin | grep 'HEAD branch:' | cut -d : -f 2 | tr -d '[[:space:]]'`
commit_sha=`git show --format='%H' --no-patch`

echo '[ERROR] 下記でエラーになった場合、実行中のブランチが古いのが原因なので git rebase を行ってください'
git merge-base --is-ancestor origin/${default_branch} ${commit_sha}

解説

  • デフォルトブランチがmainとかmasterとかdevelopとか気にしたくないので自動で判断するようにしています
  • commit_sha (現在のコミットハッシュ)に関しては、各CIで環境変数があるのでそれを利用するといいでしょう
    • GitHub Actionsだと GITHUB_SHA *1
    • GitLab CIだと CI_COMMIT_SHA *2
  • もし現在のコミットハッシュが最新のmainブランチよりも古かった場合には git merge-base --is-ancestor *3 でエラーになります
  • CIがエラーになったらだいたいみんなログを見に行くと思うので、チェックコマンドの直前に雑にechoでエラーログを出しています

おまけ:実際にGitLab CIで動かしてるやつ

GitLab CIの場合、ジョブ実行時点でremoteのブランチの内容が取ってこれていないため明示的に git fetch しています。

before_script:
  - "default_branch=`git remote show origin | grep 'HEAD branch:' | cut -d : -f 2 | tr -d '[[:space:]]'`"
  - git fetch
  - echo '[ERROR] 下記でエラーになった場合、実行中のブランチが古いのが原因なので git rebase を行ってください'
  - git merge-base --is-ancestor origin/${default_branch} ${CI_COMMIT_SHA}

2024/06/28 22:06追記:GitHub Actionsの場合の注意点

GitHub Actionsの actions/checkout はデフォルトで 最新1件の履歴しかcheckoutしない (v4時点)*4という仕様なので、PRのブランチで git merge-base --is-ancestor origin/main ${GITHUB_SHA} をしてもorigin/mainが指すコミットハッシュが存在せずエラーになります。

そのため、fetch-depth: 0 にして全ての履歴をckeckoutするか、fetch-depth: 100 のように十分に大きい数値を指定する必要があります。(個人的には後者を推奨)