🍇

【GitHub Actions】サブモジュールの変更を自動で反映する

2023/11/07に公開

業務で Git submodule を使っているのですが、サブモジュールが変更されたときにサブモジュールを参照しているリポジトリのサブモジュールを自動で最新にしたいと思い、GitHub Actions で実装してみました。

■ リポジトリ

■ GitHub Actions の流れ

  1. サブモジュールのmainブランチに変更をプッシュする
  2. サブモジュールのワークフローで、サブモジュールを参照しているリポジトリにサブモジュールが変更されたことを通知する
  3. サブモジュールを参照しているリポジトリのワークフローで、サブモジュールを更新する

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-refsubmodule-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-sampleREADME.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のサブモジュールのコミットが最新になれば完了です。

参考にさせていただいた記事

Actions

Discussion