【Github Actions】checksで失敗があればmergeできないようにしてdevelopの汚染を防ぐ
概要
github上でchecksに失敗がある場合にmergeボタンを押せないようにします。
設定するのは
- github actions
- repository settings
の2点のみです。
背景
github上でmonorepoで運用していると複数のchecksが走ると思います。
その全ての状態を確認した後にmergeする作業でミスしてしまい、不正な状態のまま運用ブランチにmergeしてしまうと復旧が必要になったりして思わぬ事故に繋がってしまうので、そのミスを発生させないように実施した内容が今回のものになります。
目的
上記の背景で述べた問題の防止策をgithub上で構築します。
その防止策としては自動的に全てのchecksの状態を確認して問題がある場合はmergeボタンを押せないようする設定を行いました。
設定・作成内容
github actionsの作成
まずは全てのchecksの状態を確認するgithub actions(ci-checks.yaml)[1]を.github/workflows内に作成します。
name: check-ci-failed
on:
push:
branches:
- '**'
- '!main'
- '!develop'
defaults:
run:
shell: bash
jobs:
check-ci-failed:
name: check-ci
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
runs-on: ubuntu-latest
steps:
- name: check ci
run: |
# 後の状態チェックでこのsuiteは除くのでidを取得する
CHECK_SUITE_ID=$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" | jq -r '.check_suite_id')
SECONDS=0
echo "CHECK_SUITE_ID:${CHECK_SUITE_ID}"
# 今回のsuiteに何が入っているのか確認のlogを出す
SUITES=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/check-suites" \
| jq -r ".check_suites[]")
echo "${SUITES}"
# 全てのciが完了するまで待機
while [ ${SECONDS} -lt 900 ] # 15分
do
STATUS=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/check-suites" \
| jq -r ".check_suites[] \
| select(any(.app;.slug != \"dependabot\")) \
| select(.id != ${CHECK_SUITE_ID}) \
| .status" \
| sort \
| uniq)
echo "Current STATUS: ${STATUS}"
[ "${STATUS}" = "completed" ] && break
sleep 30
done
# checksの結果を取得
RESULT=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/check-suites" \
| jq -r ".check_suites[] \
| select(any(.app;.slug != \"dependabot\")) \
| select(.id != ${CHECK_SUITE_ID}) \
| .conclusion" \
| sort \
| uniq)
echo "RESULT:${RESULT}"
# 結果が全てsuccess、neutral、skippedなら成功
echo "$RESULT" | grep -v -E "(success|neutral|skipped)" && exit 1 || exit 0
ファイルを作成してpushできたらgithub上で動作確認をします。
他のcheckが正常に終了している時にこのcheckがOKになっていることを確認できれば完了です。
github上での設定
該当するリポジトリのSettings > Branches > Branch protection ruleを選択してmerge時に保護したいbranchに対してルールを追加します。
mergeブロックするためにはRequire status checks to pass before mergingにチェックを入れて、上記で作成したcheck-ciを選択して完了します。
以上で設定は完了です。
エラーになるとmergeボタンが非活性になって押せないことが確認できます。
注意点
このactionがpush eventに紐づいているのでPRを作成しているのかに関係なくpushすれば動作してしまいます。
そのためPRに紐づけて処理するような別のactionがあると実行が終わらずに無駄なエラーが出てしまう可能性があるので、その部分で改善が必要です。(GCPと連携させている場合にqueuedのまま処理が終わらずにエラーになるケースに私は遭遇しています)
pull requestで動作させられればいいのですが、使用しているgithub APIがpush eventでしか動作しない[2]ので今回はこの形で使用しています。
Discussion