🎭

Github Actionsでブランチ間のPRを出す

に公開

Github Actionsでやりたいこと

以下の★の部分の作業を楽にしたい。

  • 1つのリポジトリに、ブランチが2つある(branchA、branchB)
  • branchAは、都度featureブランチからのプルリクエスト(以下PR)をマージしていく
  • ★branchBは、不定期にbarnchAからPRしてマージする
    • とりあえず手動でAction Runする

★branchBは、不定期にbarnchAからマージする でやっていること

地味に面倒くさいのです。

  • PR出す
  • タイトルに日付を入れる
  • 差分のPRは何かを書く(- #123でPR名を記述する)

↓マージPRを出したときの完成形

準備

リポジトリ

  • 適当にリポジトリを用意
  • branchA, branchBを作る
  • branchAにfeatureを適当にマージしておく
  • .github/workflowsの下にワークフローを記述するymlを作る。例:.github/workflows/pr-branchA-into-branchB.yml

PAT

personal accsess tokenでGithub Actionsに権限を与えています。

自分のプロフィールのSetting
→左のメニューの一番下にあるDeveloper Settings
→Personal access tokens (classic)

(fine grained ではよくわからなかった)

PATの設定

PATの設定は、使用するGithubレポジトリで
Settings -> Secrests and variables -> Actions から Actions secrets and variablesページに移動して、SecretsタブでMY_PERSONAL_ACCESS_TOKENを作ってtokenを貼り付ける。

なお、コード中ではこのようにして読み出すことになる:secrets.MY_PERSONAL_ACCESS_TOKEN

コード

まとめ

  • 所望の操作はできました
  • Github Actionsは自作するのは初めてだったので感想
    • Github Actionsは、yml+シェルスクリプトなのだな、と思いました
    • ChatGPT4が微妙な提案をしてくる(Actionsに新しい部分があるから)
    • トライアンドエラーに時間がかかるのが課題
    • TODO:stepは失敗するがworkflowは成功する、とかをキャッチしてエラーメールを出したい
    • TODO:自動化したい

注意

  • 同じ内容でPRを出すとエラー
  • 修正はローカルからやったほうがよい(Actionsではできなさそう)
  • PRの出し直しをすると番号が変わる。そこを気にならないならPRを削除して出し直せばよい

Appendix コードの中身


手動でのトリガー

on:
  workflow_dispatch:

    steps:
    - name: Checkout target branch
      uses: actions/checkout@v2
      with:
        ref: ${{ env.BRANCH_TARGET }}
        fetch-depth: 0  # Ensure all history is fetched
  • checkoutしてくる
  • fetch-depth: 0 はリポジトリの全ての履歴をフェッチする。デフォルトはfetch-depthは1に設定されており、最新の1つのコミットのみがフェッチされる。

echo "PR_NUMBERS=$PR_NUMBERS" >> $GITHUB_ENV
  • この書き方で、以降のステップでもPR_NUMBERSが呼び出せる。GITHUB_ENVは環境変数。
  • #は環境変数に入らないので、grep -oE 'Merge pull request \#([0-9]+)' |awk -F'#' '{print $2}' で入らないようにしている。最後に追加している。

PR_TITLE="$(TZ=Asia/Tokyo date +'%Y/%m/%d') Update"

タイムゾーンはUTCになっているので日本時間にすること。


        PR_BODY="## Included PRs\\n"
        # Convert space-separated PR numbers into an array
        IFS=' ' read -ra PR_ARRAY <<< "$PR_NUMBERS"
        for pr in "${PR_ARRAY[@]}"; do
          PR_BODY+="- #$pr\\n"
        done

改行はJSONに入れるときに\\n(スラッシュ2つ)にすること


        # Escape for JSON
        PR_BODY_JSON=$(echo "$PR_BODY" | sed 's/"/\\"/g')

JSONに入れるときにダブルクォートは \"にするための処理


        # Create PR using GitHub API
        curl -L \
          -X POST \
          -H "Accept: application/vnd.github+json" \
          -H "Authorization: Bearer ${{ secrets.MY_PERSONAL_ACCESS_TOKEN }}" \
          -H "X-GitHub-Api-Version: 2022-11-28" \
          https://api.github.com/repos/$GITHUB_REPOSITORY/pulls \
          -d "{\"title\":\"$PR_TITLE\",\"body\":\"$PR_BODY_JSON\",\"head\":\"${{ env.BRANCH_SOURCE }}\",\"base\":\"${{ env.BRANCH_TARGET }}\"}"

このAPIの記法はこちらに

https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#create-a-pull-request


env:
  BRANCH_SOURCE: branchA
  BRANCH_TARGET: branchB

で変数を設定して、

    - name: Extract PR numbers from commit messages
      run: |
        # Extract PR numbers and format as a space-separated string
        PR_NUMBERS=$(git log --oneline origin/${{ env.BRANCH_TARGET }}..origin/${{ env.BRANCH_SOURCE }} | 
                     grep -oE 'Merge pull request \#([0-9]+)' | 
                     awk -F'#' '{print $2}' | 
                     sort -n | 
                     tr '\n' ' ')

--oneline origin/${{ env.BRANCH_TARGET }}..origin/${{ env.BRANCH_SOURCE }} としているのですが、origin の場所がここにしないとうまく行きませんでした。GithubActionsのどこから見てoriginなのかイマイチ理解できていないです。チェックアウトしたブランチから見るとoriginはいらないような気がするのですが。

Discussion