【GitHub Actions】サブモジュールの変更を自動で反映する
業務で Git submodule を使っているのですが、サブモジュールが変更されたときにサブモジュールを参照しているリポジトリのサブモジュールを自動で最新にしたいと思い、GitHub Actions で実装してみました。
■ リポジトリ
- submodule-sample : サブモジュール
- submodule-sample-ref : サブモジュールを参照するリポジトリ
■ GitHub Actions の流れ
- サブモジュールの
main
ブランチに変更をプッシュする - サブモジュールのワークフローで、サブモジュールを参照しているリポジトリにサブモジュールが変更されたことを通知する
- サブモジュールを参照しているリポジトリのワークフローで、サブモジュールを更新する
submodule-sample-ref
にワークフローを実装する
■ サブモジュールが変更されたときに実行するワークフローを実装します。
GitHub API とワークフローの連携を確認するために、まずはメッセージを表示するだけの簡易的なワークフローを実装します。
.github/workflows/update_submodule.yml
name: Update Submodule
on:
repository_dispatch:
types:
- update
jobs:
update_submodule:
runs-on: ubuntu-latest
steps:
- name: Show message
run: echo "Hello"
repository_dispatch
について
-
repository_dispatch
は、Webhook イベントをトリガーできるペイロード -
types
を指定すると Webhook で特定のevent_type
が送られてきたときに、ワークフローを実行することができる
■ 変更を通知するワークフローを実装する
submodule-sample
に、サブモジュールの変更を通知するワークフローを実装します。
GitHub API を使うためにアクセストークンが必要になるので「GitHub Apps token」または「Personal access tokens」から生成します。
GitHub Apps token
Github Apps の登録
- GitHub Apps から「New GitHub App」を選択
- 以下を入力
- GitHub App name
- Description
- Homepage URL
- Webhook の Active のチェックを外す
- Repository permissions から以下を選択
- Contents: Read and write
- Metadata: Read-only
- Only on this account にチェック
- 入力が完了したら「Create GitHub App」を選択
秘密鍵の生成
「Generate a private key」を選択して、秘密鍵をダウンロードします。
GitHub App のインストール
Install App から Install を選択するとリポジトリの選択画面が表示されるので、Only select repositories
からsubmodule-sample-ref
とsubmodule-sample
を選択して、Install をクリックします。
App ID と秘密鍵を Secrets に登録する
「submodule-sample/Settings/Secrets and variables/Actions/Secrets タブ
」から、以下を登録します。
- APP_ID : 作成した GitHub Apps の App ID
- PRIVATE_KEY : ダウンロードした秘密鍵
登録が完了したら、ダウンロードした秘密鍵を削除しておきます。
ワークフロー
.github/workflows/dispatch_update.yml
name: Dispatch update
on:
push:
branches:
- main
jobs:
dispatch:
runs-on: ubuntu-latest
steps:
- name: Generate GitHub Apps token
uses: tibdex/github-app-token@v2
id: create_token
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.PRIVATE_KEY }}
- run: |
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ steps.create_token.outputs.token }}" "https://api.github.com/repos/[user]/submodule-sample-ref/dispatches" -d '{ "event_type": "update" }'
Personal access tokens
以下でトークンを生成して「submodule-sample/Settings/Secrets and variables/Actions/Secrets タブ
」から、DISPATCH_TOKEN
を登録します。
Tokens(classic)
- Select scopes
- repo にチェック
Fine-grained tokens
- Only select repositories
- submodule-sample-ref
- Repository permissions
- Contents: Read and write
- Metadata: Read-only
ワークフロー
.github/workflows/dispatch_update.yml
name: Dispatch update
on:
push:
branches:
- main
jobs:
dispatch:
runs-on: ubuntu-latest
steps:
- run: |
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.DISPATCH_TOKEN }}" "https://api.github.com/repos/[user]/submodule-sample-ref/dispatches" -d '{ "event_type": "update" }'
ワークフローの実装が完了してリモートリポジトリに反映したら、submodule-sample
のREADME.md
など適当なファイルを編集して、上記のワークフローとsubmodule-sample-ref
のワークフローが実行されることを確認します。
Create a repository dispatch event
■ サブモジュールを最新にするワークフローを実装する
submodule-sample-ref
に、サブモジュールを最新にするワークフローを実装します。
.github/workflows/update_submodule.yml
name: Update Submodule
on:
repository_dispatch:
types:
- update
workflow_dispatch:
jobs:
update_submodule:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.GHA_SSH_PRIVATE_KEY }}
submodules: recursive
- name: Update submodule
run: git submodule update --remote
- name: Check git status
id: status
run: echo "status=$(git status -s)" >> $GITHUB_OUTPUT
- name: Commit
run: |
git config --local user.name "Github Actions"
git config --local user.email "action@github.com"
git add .
git status
git commit -m "Update submodule"
if: ${{ steps.status.outputs.status }}
- name: Push
uses: ad-m/github-push-action@master
with:
branch: main
github_token: ${{ secrets.GITHUB_TOKEN }}
if: ${{ steps.status.outputs.status }}
GHA_SSH_PRIVATE_KEY
ローカルで ssh の公開鍵と秘密鍵を生成して、公開鍵を「submodule-sample/Settings/Deploy keys
」、秘密鍵をGHA_SSH_PRIVATE_KEY
という名前で「submodule-sample-ref/Settings/Secrets and variables/Actions
」に設定します。
# 鍵を生成
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_submodule_workflow
# 公開鍵のコピー
$ pbcopy < ~/.ssh/id_ed25519_submodule_workflow.pub
# 秘密鍵のコピー
$ pbcopy < ~/.ssh/id_ed25519_submodule_workflow
Actions permissions
「submodule-sample-ref/Settings/Actions/General/Workflow permissions
」を「Read and write permissions」に設定します。
submodule-sample
のファイルを変更してmain
ブランチにプッシュしたときに、submodule-sample-ref
のサブモジュールのコミットが最新になれば完了です。
参考にさせていただいた記事
- GIthub Actions で Git Submodule を 最新に更新して処理する
- GitHub Appsトークン解体新書:GitHub ActionsからPATを駆逐する技術
- [GitHub]secrets.GITHUB_TOKENで実行できる権限について簡単ながらマッピングしてみた
Discussion