LoginSignup
5
2

github actionsでPRを自動作成したけどbranch protection用のジョブがトリガーされない

Posted at

はじめに

前回の記事で、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が起動しなかった(以下の状態がずっと)
    1-1.png

    • 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する

要は以下のようになればいい
1-2.png

github に追加の設定を入れないのですぐ対処できる。簡単。
だけど自動作成したPRをそのままポチッとmerge出来ないのでちょっと面倒。

自動作成されたPRに対して空commitをpushする

  • git commit --allow-empty && git push

自動作成されたPRを一旦closeし、reopenする

  • closeして、reopen
    1-3.png

ちょっとひと手間だけど根本解決

  • PR作成時のgithub CLIを使う権限を強くする

organizationにgithub appsを連携させて、git appsのtoken権限を利用する方法
githubに権限設定を加えるので、セットアップが面倒くさい。
だけど自動作成したPRをそのままポチッとmerge出来るので理想形。
organizationでPATの利用を許可して使う方法もありますが、個人に紐づく情報はそもそもorganizationにおいては使わないほうがいいです。
なので個人に紐づかないgithub appsを使います。

GitHub AppsのOrganizationとの連携

  • こちらの記事がよくまとまっているので導入方法は割愛します。

  • github AppsをOrganizationと連携させるのはOrganizationのオーナー/管理者に設定して貰う必要がある。

  • PRに対してのwrite権限はつける
    1-4.png

  • 最終的なGithub Appsの設定
    1-5.png

  • App IDPrivate 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はトリガーされない
    1-6.png

まとめ

暫定的な対応でも正直全然許容レベルかなと思いましたが、パイプラインとしての理想を追い求めてみました。

参考

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2