はじめに
前回の記事で、AWS API GatewayのSDKを自動更新するパイプラインを作成しました。
その際にパイプラインからPRを作成しました。
そして、PRを作成したOrganization repositryにbranch protectionを設定していました。
branch protectionの内容としては、PRが作られたタイミングでprotection用のジョブがトリガーされ、正常終了したPRのみがmergeできるという設定です。
で、今回発生した問題が、
github actions経由で作成したPRに対して、protection用のジョブがトリガーされなかった。
そのため、mergeがblockされ続ける というものです。
解決したので記事に残します。
環境
- Organizationのgit repository
- repositoryにはbranch protectionが設定されている
- branch protectionは以下の条件で設定されている
- 最低一人のreview approveが必須
- protection用のjobがそのPRに対して実行され、正常終了していること
- github actionsからPRを自動作成した
何が起きたのか
-
作成されたPRに対してbranch protectionで設定しているjobが起動しなかった(以下の状態がずっと)
-
Expected — Waiting for status to be reported
とあるのでbranch protectionのjobの正常終了を待っている状態 - もちろん
Merge pull request
は押せない
-
原因
stack overflowの投稿で書いてくれている人がいるのですが、
-
${{ secrets.GITHUB_TOKEN }}
で使用することが出来るGITHUB_TOKENの権限では、github actionsのパイプラインから、他のgithub actionsのパイプラインをトリガーすることは制限されている - そのため、GITHUB_TOKENを使って作成されたPRに対して、branch protectionのジョブをトリガーすることが出来ず、branch protectionがずっと待ち状態になる
解決方法
今回試した解決方法は「簡単な暫定解決」と、「ちょっとひと手間だけど根本解決」の2つあります。
簡単な暫定解決
- PRに対しての最後の操作を人間にする
- 自動作成されたPRに対して空commitをpushする
- 自動作成されたPRを一旦closeし、reopenする
github に追加の設定を入れないのですぐ対処できる。簡単。
だけど自動作成したPRをそのままポチッとmerge出来ないのでちょっと面倒。
自動作成されたPRに対して空commitをpushする
git commit --allow-empty && git push
自動作成されたPRを一旦closeし、reopenする
ちょっとひと手間だけど根本解決
- PR作成時のgithub CLIを使う権限を強くする
organizationにgithub appsを連携させて、git appsのtoken権限を利用する方法
githubに権限設定を加えるので、セットアップが面倒くさい。
だけど自動作成したPRをそのままポチッとmerge出来るので理想形。
organizationでPATの利用を許可して使う方法もありますが、個人に紐づく情報はそもそもorganizationにおいては使わないほうがいいです。
なので個人に紐づかないgithub appsを使います。
GitHub AppsのOrganizationとの連携
-
こちらの記事がよくまとまっているので導入方法は割愛します。
-
github AppsをOrganizationと連携させるのはOrganizationのオーナー/管理者に設定して貰う必要がある。
-
App ID
とPrivate Key
をsecretsに登録しておく
pipeline.yamlの設定
前回の記事で使ったyamlの修正差分で表す
name: update api gateway sdk
on:
...
env:
SYNC_BRANCH: hotfix/apigateway_sdk_update
- GH_TOKEN: ${{ github.token }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
permissions:
id-token: write
contents: write
pull-requests: write
jobs:
build:
name: get sdk
runs-on: ubuntu-latest
steps:
+ - name: Generate token
+ id: generate_token
+ uses: tibdex/github-app-token@v1
+ with:
+ app_id: ${{ secrets.APP_ID }}
+ private_key: ${{ secrets.PRIVATE_KEY }}
+ - name: tokenの設定
+ run: |
+ echo GH_TOKEN=${{ steps.generate_token.outputs.token }} >> "$GITHUB_ENV"
- name: Checkout
uses: actions/checkout@v3
+ with:
+ token: ${{ env.GH_TOKEN }}
...
- name: ブランチ作成/更新
id: create-sync-branch
if: env.NEW_SDK_CHECKSUM != env.OLD_SDK_CHECKSUM
run: |
git config user.email "actions@github.com"
git config user.name "Github Actions"
branch=${{ env.SYNC_BRANCH }}
git switch -C $branch
git add .
git commit -m "update AWS API Gateway SDK from Github actions"
git push -f origin $branch
- name: PR作成済みチェック
id: check_pr
if: env.NEW_SDK_CHECKSUM != env.OLD_SDK_CHECKSUM
run: |
pr_title='API Gateway SDK new Update🚀'
base_branch='master'
echo "::set-output name=count::$(gh pr list -S "${pr_title}"' in:title' -B $base_branch | wc -l)"
echo "::set-output name=pr_title::$pr_title"
echo "::set-output name=base_branch::$base_branch"
- name: PR作成
if: ${{ (env.NEW_SDK_CHECKSUM != env.OLD_SDK_CHECKSUM) && (steps.check_pr.outputs.count == 0) }}
env:
TZ: 'Asia/Tokyo' # タイムゾーン指定
run: |
CURRENT_DATETIME=$(date +'%Y-%m-%d %H:%M:%S')
gh pr create -B ${{ steps.check_pr.outputs.base_branch }} -t "${{ steps.check_pr.outputs.pr_title }}" -b "🕰️make PR date: $CURRENT_DATETIME"
ポイント
Generate token
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@v1
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.PRIVATE_KEY }}
- name: tokenの設定
run: |
echo GH_TOKEN=${{ steps.generate_token.outputs.token }} >> "$GITHUB_ENV"
- Github Appsからtokenを生成し、GH_TOKENとして設定している。
-
gh pr create
でのPR作成に影響を与える(Github Apps権限での作成になる)
Checkout
- name: Checkout
uses: actions/checkout@v3
with:
token: ${{ env.GH_TOKEN }}
- Github Appsから生成したtokenをリポジトリのcheckout時に指定している
-
git push
を始めとしたgit
コマンドに影響を与える(Github Apps権限での操作になる) - 逆にこれを設定しないと
git push
はただのgithub actions権限での操作扱いになる - その場合、PRに対して後から
force push
をした時にbranch protecionはトリガーされない
まとめ
暫定的な対応でも正直全然許容レベルかなと思いましたが、パイプラインとしての理想を追い求めてみました。