GitHub Actionsで別リポジトリーにAPIクライアントのPRを作る
GA technologiesでソフトウェアエンジニアをしている相川です。
私の所属しているチームでは、メインのプロダクト上でOpenAPI Generatorを用いて生成したAPIクライアントを別リポジトリーにコピーして配布しているのですが、これを自動化できないかということで今回試してみることにしました。
実現したいこと
- OpenAPI仕様ファイルを元に、RubyのAPIクライアントを自動生成
- 生成したAPIクライアントを別リポジトリーにプッシュ
- バージョン番号を含むブランチとPRを自動作成
アーキテクチャー概要
[プロダクトリポジトリー]
├── .api-client-version(トリガーファイル)
├── docs/api_spec/openapi.yaml
└── .github/workflows/generate_api_client.yml
↓
GitHub Actions実行
↓
OpenAPI Generator でクライアント生成
↓
[APIクライアントリポジトリー]
└── 生成されたRuby Gem(自動生成されるPRによって更新)
成果物: generate_api_client.yml
on:
push:
branches:
- develop
paths:
- '.api-client-version'
jobs:
generate_api_client:
name: APIクライアントを生成する
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/create-github-app-token@v2
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: |
api_client_repo
- uses: actions/checkout@v5
with:
token: ${{ steps.app-token.outputs.token }}
repository: ga-tech/api_client_repo
path: client
persist-credentials: false
- uses: actions/setup-node@v5
with:
node-version: 24.x
- uses: actions/setup-java@v5
with:
distribution: oracle
java-version: 21
- name: Install OpenAPI Generator
run: npm install @openapitools/openapi-generator-cli -g
- name: Set OpenAPI Generator version
run: npx openapi-generator-cli version-manager set 7.11.0
- name: Get current version and increment
id: get-new-version
run: |
NEW_VERSION=$(cat .api-client-version | tr -d '\n')
echo "new-version=$NEW_VERSION" >> $GITHUB_OUTPUT
- name: Generate API client
run: openapi-generator-cli generate -i docs/api_spec/openapi.yaml -g ruby --additional-properties=gemName=api_client_name,gemVersion=${{ steps.get-new-version.outputs.new-version }},library=faraday -o ./client/
- name: Get GitHub App User ID
id: get-user-id
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Commit and push changes
run: |
cd client
git checkout -b v${{ steps.get-new-version.outputs.new-version }}
git config --global user.name "${{ steps.app-token.outputs.app-slug }}[bot]"
git config --global user.email "${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com"
git add .
git commit -m "v${{ steps.get-new-version.outputs.new-version }}"
git remote set-url origin https://${{ steps.app-token.outputs.app-slug }}[bot]:${{ steps.app-token.outputs.token }}@github.com/ga-tech/api_client_repo.git
git push origin v${{ steps.get-new-version.outputs.new-version }}
gh pr create \
--repo ga-tech/api_client_repo \
--base main \
--head v${{ steps.get-new-version.outputs.new-version }} \
--title "v${{ steps.get-new-version.outputs.new-version }}" \
--body "v${{ steps.get-new-version.outputs.new-version }}"
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
実装のポイント
GitHub Appを使った別リポジトリーへのアクセス
GitHub ActionsのデフォルトのGITHUB_TOKENには、別リポジトリーへの書き込み権限がありません。そこで今回はGitHub Appを作成し、actions/create-github-app-tokenアクションを使用してトークンを生成しました。
- uses: actions/create-github-app-token@v2
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: |
api_client_repo
GitHub Appの設定手順は以下の通りです。
- GitHub Appを作成(Settings → Developer settings → GitHub Apps)
- 必要な権限を設定(Contents: Read and write, Pull requests: Read and write)
- 対象リポジトリーにAppをインストール
- 操作したいリポジトリーを選択(今回はapi_client_repo)
- App IDとPrivate Keyをシークレットに登録
バージョン管理ファイルによるトリガー制御
.api-client-versionファイルを更新することで、ワークフローを明示的にトリガーできます。
on:
push:
branches:
- develop
paths:
- '.api-client-version'
ちなみに、OpenAPI仕様ファイルにもバージョンは設定できますが、こちらを使うと生成されるファイルの差分が非常に多岐にわたってしまうため、利便性を優先してこうした仕組みにしました。
OpenAPI Generatorの設定
OpenAPI Generatorのバージョンを固定することで、生成結果の一貫性を保ちます。また、このバージョンも変更するとファイルの差分が多岐にわたってしまうという背景もあります。
- name: Install OpenAPI Generator
run: npm install @openapitools/openapi-generator-cli -g
- name: Set OpenAPI Generator version
run: npx openapi-generator-cli version-manager set 7.11.0
GitHub App Botとしてのコミット
GitHub Appの正規のBot IDとメールアドレスを取得し、コミット作成者として設定します。これにより、GitHubのUIでBotアイコンが正しく表示されます。
- name: Get GitHub App User ID
id: get-user-id
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
- name: Commit and push changes
run: |
git config --global user.name "${{ steps.app-token.outputs.app-slug }}[bot]"
git config --global user.email "${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com"
PR自動作成
GitHub CLIを使用してPRを作成します。バージョン番号をブランチ名、タイトル、本文に使用しています。
gh pr create \
--repo ga-tech/api_client_repo \
--base main \
--head v${{ steps.get-new-version.outputs.new-version }} \
--title "v${{ steps.get-new-version.outputs.new-version }}" \
--body "v${{ steps.get-new-version.outputs.new-version }}"
実行例
-
.api-client-versionを1.0.0から1.1.0に更新 -
developブランチにプッシュ - GitHub Actionsが実行される
-
api_client_repoリポジトリーに以下が作成される:- ブランチ:
v1.1.0 - PR: タイトル「v1.1.0」
- コミット: Botユーザーによる自動生成コード
- ブランチ:
実装時の注意点
Java環境が必要
OpenAPI Generatorの実行にはJava 11以上が必要です。
- uses: actions/setup-java@v5
with:
distribution: oracle
java-version: 21
persist-credentials: false の設定
別リポジトリーのチェックアウト時に、GitHub App tokenを使用するためpersist-credentials: falseを設定します。
- uses: actions/checkout@v5
with:
token: ${{ steps.app-token.outputs.token }}
repository: ga-tech/api_client_repo
path: client
persist-credentials: false
重複PRの防止
同じブランチ名でPRが既に存在する場合、gh pr createはエラーになります。必要に応じて、既存のPRチェックやブランチ削除のロジックを追加しても良いかもしれません。
まとめ
GitHub Actionsを活用することで、OpenAPI仕様ファイルからAPIクライアントを自動生成し、別リポジトリーにPRを作成するワークフローを実現できました。これにより、手動作業が削減されたこともありますが、チームメンバー各自がそれぞれOpenAPI Generatorをインストールする必要が無くなったということも大きいと思います。
重複PRの防止をはじめ、作られたPRのタイトルと内容がバージョンだけで素っ気ないなどの課題はありますが、その辺は追々改善していければと考えています。
Discussion