GitHub Actionsのワークフロー内で、gh apiコマンドを活用してPull Requestの本文(リリースノート)を自動生成するTips

エンジニアの中田です。現在、社内の有志エンジニアが協力して、Goodpatch 社内向けのツールを開発しています。このプロジェクトで、私は iOS App を開発しており、GitHub Actions を使用して社内メンバーへのリリースフローを自動化しています。本記事では、gh api コマンドを活用して Pull Request の本文(リリースノート)を自動生成する Tips を紹介します。


この iOS プロジェクトは、トランクベース開発のスタイルで実装を進めています。

社内にリリースする際は、repo 内の GitHub Actions のページから、該当するワークフローを選び Run workflow をクリックします。

Run workflow メニューからワークフローを実行

このワークフローが、Release 用ブランチと Pull Request を作成します。その後、この Pull Request を main ブランチにマージすると、iOS App をビルドするワークフローが走り、Firebase App Distribution へ ipa ファイルをアップロードする流れです。


Pull Request の本文(リリースノート)を自動生成

Pull Request の本文には、前回のリリースとの差分をもとに作成したリリースノートを記述して、変更履歴を残したいと思います。

GitHub には、GitHub Release のリリースノートを自動的に生成する機能があります。

Automatically generated release notes - GitHub Docs

今回はこの機能の API を利用します。

POST /repos/{owner}/{repo}/releases/generate-notes

GitHub Actions からこの API を呼び出す方法はいくつかあると思いますが、今回は、GitHub CLI の gh api コマンドを使います。API を呼び出してリリースノートの本文をBODYへ代入するコードは次のとおりです。

BODY=$(gh api --method POST -H "Accept: application/vnd.github+json" /repos/{owner}/{repo}/releases/generate-notes -f tag_name="v$VERSION" -f target_commitish='main' | jq --raw-output .body)

jq --raw-output するとunescapeされた文字列を出力してくれます。

Pull Requestを作成

Pull Request は、GitHub CLI の gh pr createを使って作成します。

gh pr create --base main --head "release/v$VERSION" --title "release v$VERSION" --body "$BODY" --label "release"

このコマンドを実行すると、次のような Pull Request が作成されます 🎉

GitHub Actionsで作成したPull Requestの例

GitHub Actions のワークフロー

このワークフロー .github/workflows/create_release_pr.yml の全文は次のとおりです。

name: Create a Release Pull Request

on:
  workflow_dispatch:

jobs:
  create_pr:
    runs-on: macos-12

    steps:
      - uses: actions/checkout@v3
      
      # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-ruby#caching-dependencies
      - uses: actions/cache@v3
        with:
          path: vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-

      - name: Bundle install
        run: |
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3

      - name: Bump minor version then create a release branch and tag
        run: bundle exec fastlane bump_minor

      - name: Create a pull request
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          VERSION=$(agvtool what-marketing-version -terse1)
          BODY=$(gh api --method POST -H "Accept: application/vnd.github+json" /repos/{owner}/{repo}/releases/generate-notes -f tag_name="v$VERSION" -f target_commitish='main' | jq --raw-output .body)
          gh pr create --base main --head "release/v$VERSION" --title "release v$VERSION" --body "$BODY" --label "release"

補足

on:
  workflow_dispatch:

ワークフローを実行するトリガーとして workflow_dispatch を指定することで、手動でワークフローを実行できるようになります。

Fastfile

iOS Appのバージョンとビルド番号を更新する処理、リリース用のブランチの作成、tagの追加は、fastlane を使っています。

fastlane/Fastfileの該当箇所を抜粋します。

# fastlane/Fastfile

desc "Bump minor version"
lane :bump_minor do
  increment_version_number(bump_type: "minor")
  increment_build_number
  commit_and_tag
end

def commit_and_tag
  version_number = get_version_number target: 'XXX'
  build_number = get_build_number
  branch_name = "#{version_number}"
  message = "ci: bump version v#{version_number} (#{build_number})"

  sh "git checkout -b 'release/v#{branch_name}'"
  sh "git commit -a -m '#{message}'"
  sh 'git push origin HEAD'

  add_git_tag(tag: "v#{version_number}")
  sh 'git push --tags'
end

前述のワークフローの次の箇所で実行されます。

run: bundle exec fastlane bump_minor

リリースノート本文のカスタマイズ

GitHub Releaseのリリースノートは .github/release.yml でカスタマイズできます。先ほどの Pull Request のスクリーンショットでは、次の release.yml を使用しています。

changelog:
  categories:
    - title: Features
      labels:
        - enhancement
        - feature
    - title: Bug Fixes
      labels:
        - bug
    - title: Other Changes
      labels:
        - "*"

カスタマイズの詳細は Configuring automatically generated release notes - GitHub Docs を参照してください。

おわりに

GitHub Actions のワークフロー内で gh コマンドを実行することで、簡単にリリースノートを自動作成したり、Pull Request を作成できることが分かりました。

今回、自動生成したリリースノートは、Pull Requestの本文として利用していますが、Pull Request本文を GitHub Actionsのワークフローから参照することで、Firebase App Distributionのリリースノートにも活用できそうです。