GitHub Actionsの自動マージが、次のworkflowを起動しない ― 2ヶ月「直っていない」と思い込んでいたバグの正体
前回の記事で、個人開発のMinecraftサーバー監視アプリ「MineWatch」(公式サイト、アプリの全体像はこちら)のPRを、AIレビューと機械的な検証で自動マージする仕組みを紹介しました。今回は、その自動マージの「次」でハマった話です。
developへのPRがAIレビューでAPPROVEになり、squashマージされたはずなのに、その後に走るはずのstagingビルドが動かないことがありました。対策は入れたつもりでしたが、TODOリストには2ヶ月近く「未解決」のまま残っていました。実際には、原因の切り分けを間違えていただけで、対策自体はもっと前から効いていた、という話です。
TL;DR
- developへのPRを自動マージ(squash)したあと、それをきっかけに走るはずの
pushイベント発火のworkflowが起動しないことがある。原因は、GitHub ActionsのGITHUB_TOKENで行った操作は、他のworkflowの起動トリガーにならないという公式の仕様。 - 対策は素朴で、squashマージにpersonal access token(PAT)を使うだけ。ただし1回目のテストでは、PATをsecretsに登録する6分前に検証用のPRをマージしてしまい、「直っていない」という間違った結論を出してしまった。
- この間違った結論はTODOリストに残り続け、2ヶ月ほど「未解決のバグ」として扱われていた。実際に直っていることに気づいたのは、別件の記録作業でたまたま自動マージが走った時だった。
- 教訓: 「直したはず」で終わらせず、実際に効いたことを確認するところまでやる。古いTODOは、内容を信じる前に、まず現在の状態を確認する。
1. 症状: developへの自動マージ後、staging反映が動かない
MineWatchは、developブランチへのPRがJenkinsのAIレビューでVERDICT: APPROVEになると、GitHub Actions(copilot-review-handler.yml)がGitHub CLIでsquashマージします。
gh pr merge "${PR_NUMBER}" \
--squash \
--delete-branch \
--auto \
--match-head-commit "${REVIEWED_SHA}"
developへのpushをきっかけに、別のworkflow(staging-deploy-trigger.yml)がJenkinsのstagingビルドを起動する設計になっています。ところが、自動マージ経由でマージされたときだけ、このstagingビルドが起動しないことがありました。手動でマージしたときは問題なく動きます。
2. GitHubの仕様: GITHUB_TOKENでの操作はworkflowを起動しない
原因は、GitHub Actionsの仕様でした。公式ドキュメントには、こう書かれています。
When you use the repository's
GITHUB_TOKENto perform tasks, events triggered by theGITHUB_TOKENwill not create a new workflow run, with the following exceptions:workflow_dispatchandrepository_dispatchevents always create workflow runs.
つまり、workflow内で既定のGITHUB_TOKENを使ってpush・マージなどの操作をしても、それをトリガーにした別のworkflowは起動しません。これは、workflowがworkflowを無限に呼び合う事故を防ぐための、意図的な制限です。回避策として公式に案内されているのが、GitHub Appのインストールトークンか、personal access token(PAT)を使うことでした。
3. 対策: RELEASE_PATを発行してsecretsに登録した
対策として、squashマージ専用のPAT(RELEASE_PAT)を発行し、リポジトリのsecretsに登録しました。workflow側は、これが無ければ既定のGITHUB_TOKENにフォールバックする形にしています。
env:
# RELEASE_PAT が無ければ GITHUB_TOKEN にフォールバック。
# ブランチ保護の必須チェックを越えるには PAT が要ることがある。
GH_TOKEN: ${{ secrets.RELEASE_PAT || secrets.GITHUB_TOKEN }}
4. 1回目のテストで「直っていない」と判断した
対策を入れた直後、実際に1本のPRで動作を確認しました。ところが、マージ後のmerged_byがgithub-actions[bot]のままで、狙っていた「PATのユーザーとしてマージされる」という状態になっていませんでした。stagingビルドも起動しませんでした。
このときの結論は「RELEASE_PATを発行してsecretsに登録したが、1回目のテストではmerged_byがgithub-actions[bot]のままで未解決。secret再登録して再検証中」でした。この文言はそのままTODOリストに残り、以後2ヶ月近く「未解決のバグ」として扱われることになります。
5. 2ヶ月後、たまたま実地検証したら直っていた
別件のドキュメント修正PRを2本、developに向けて出したときのことです。1本目(TODOのチェック漏れを直すだけの小さなPR)をマージしたところ、自動マージのコメントから数秒でstagingビルドのworkflowが起動しました。
コメント投稿: 14:35:14
自動マージ完了: 14:35:31(merged_by: 実アカウント、botではない)
staging-deploy-trigger.yml 起動・成功: 14:35:33
merged_byが実アカウント(PATの所有者)になっていて、マージから2秒後にstagingビルドが正常に起動していました。「未解決」としてTODOに残っていたバグが、実は解決済みだったことが分かった瞬間です。
6. 原因: RELEASE_PAT登録の6分前にテストしていた
なぜ1回目のテストで失敗したのか、GitHub上の記録を洗い直しました。
RELEASE_PAT の secrets 登録: 03:08
1回目のテストPRのマージ: 03:02(登録の6分前)
secretsへの登録より6分前に、検証用のPRをマージしていました。secrets.RELEASE_PAT || secrets.GITHUB_TOKENは、その時点ではRELEASE_PATが未登録(空)だったので、想定どおりGITHUB_TOKENにフォールバックしていただけでした。「直したはずなのに直っていない」ように見えたテストは、そもそも対策が入る前の状態を測っていたことになります。バグの再現でも、対策の失敗でもありませんでした。
さらに調べると、その後developへのマージは、ほぼ全部を手動で行っていました。自動マージの経路自体が、2ヶ月間ほとんど実行されていなかったのです。「間違った1回のテスト結果」が訂正される機会もなく、そのままTODOに残り続けていました。
まとめ
- GitHub Actionsの
GITHUB_TOKENでのマージ・pushは、他のworkflowの起動トリガーにならない。回避にはPATかGitHub Appトークンが要る。 - 対策そのものは正しかったが、検証したタイミングが対策の反映前だったため、間違った「未解決」判定を下してしまった。
- 間違った判定は、再検証されないまま2ヶ月間TODOリストに残った。自動マージの経路自体がその間ほとんど使われていなかったことも、気づく機会を減らしていた。
- 古いTODOやメモに書かれた「未解決」を、そのまま信じて次の対応を組み立てるのは危険。可能なら、まず現在の状態を実地で確認してから動く。今回は、たまたま別件のPRで自動マージが走ったことで、思い込みに気づけた。
個人開発の環境での構成なので、そのまま組織に持ち込む場合は、PATの権限範囲や有効期限の運用ルールを先に確認してください。
JQITのエンジニアの95%以上は未経験からの採用です。
よければコーポレートサイトにも遊びに来てください。
未経験から学べます!一緒に挑戦していきましょう![]()
noteやXもやってます↓