はじめに
ポートフォリオサイトを、Github Actionsでビルド・Github Pagesで公開というように運用しているんですが、他のリポジトリにあるプロジェクトもGithub Pagesで公開したくなることがありました。Github Pagesのリポジトリで、公開したいプロジェクトのリポジトリをGit Submoduleとして参照することで、これは実現できます。しかしこのままでは、Github PagesのリポジトリでSubmoduleを更新しないと、参照先のリポジトリへの変更が適用されません。これは面倒なので、参照先リポジトリが変更されたタイミングで、自動でSubmoduleを更新してビルドをするようなものを作りました。
WebhookでWorkflowをトリガーする
Github ActionsのWorkflowは、特定の条件でそれが起動するように記述します。例えば、「masterブランチにpushされた」などです。前述のようなことを実現するには「リポジトリAのmasterブランチにpushされた」をトリガーに、リポジトリBのWorkflowを起動できれば良さそうです。しかし、直接そのようなトリガーを記述することはできません。
そこで使うのが repository dispatch event です。repository dispatch event を使えば、リポジトリ外部からのAPI呼び出しをトリガーにすることができます。
参考:Github Actions を API から実行する - Qiita
以下、Submodule参照元のリポジトリをsubmod_action_main、Submodule参照先のリポジトリをsubmod_action_sub とします。
GitHub - w-haibara/submod_action_main
GitHub - w-haibara/submod_action_sub
参照元リポジトリ submod_action_main に、repository dispatch event でトリガーするWorkflowを作成します。
下記のWorkflowは「このリポジトリに対してAPI呼び出しがあったとき、Github Actions上でecho "Hello!" を実行する」ものです。
name: Update Submodule
on:
repository_dispatch:
types: [update]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Hello
run: |
echo "Hello!"このWorkflowを実行するためのAPI呼び出しは、以下のようにcurlで行うことができます。
この際、指定するURLは、
https://api.github.com/repos/<ユーザー名>/<リポジトリ名>/dispatches
となります。
また、環境変数 DISPATCH_TOKEN は、API呼び出しの対象とするリポジトリのシークレットです。
ターミナルで下記のcurlを実行してみます。
curl -vv \[f:id:w_haibara:20200613025711p:plain]
-H "Authorization: token ${{ DISPATCH_TOKEN }}" \
-H "Accept: application/vnd.github.everest-preview+json" \
"https://api.github.com/repos/w-haibara/submod_action_main/dispatches" \
-d '{"event_type": "update"}'実行すると、Status: 204 No Content が帰ってくると思います。
Workflowの実行結果を見てみると、echo "Hello!" が実行されていることを確認できます。


これで、Web APIを通して外部からトリガーできるWorkflowを作ることができました。
WorkflowからAPI呼び出し
次に、先ほどターミナル上のcurlで行ったAPI呼び出しを、Workflowから行います。
下記に、「masterブランチにpushがあったとき、API呼び出しを行う」Workflowを示します。
ここで ${{ secrets.DISPATCH_TOKEN }} としている部分は、Github内に DISPATCH_TOKEN という名前で登録した、API呼び出しの対象とするリポジトリのシークレットです。
name: Dispatch
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: |
curl -vv -H "Authorization: token ${{ secrets.DISPATCH_TOKEN }}" -H "Accept: application/vnd.github.everest-preview+json" "https://api.github.com/repos/w-haibara/submod_action_main/dispatches" -d '{"event_type": "update"}'submod_action_sub/dispatch.yml at master · w-haibara/submod_action_sub · GitHub
このWorkflowと、先ほどのrepository dispatch event を組み合わせると、冒頭で言っていた「リポジトリAのmasterブランチにpushされたら、リポジトリBでビルドをする」ということが可能となります。
(リポジトリAのmasterブランチにpush --> Web API 呼び出し (リポジトリAのWorkflow) --> repository dispatch eventが発火 (リポジトリBのWorkflow) --> リポジトリBのビルド)
Submoduleの更新
後は、参照元のリポジトリ(repository dispatch event を使ったリポジトリ)で、Submoduleを更新してビルドするだけです。Workflowは下記のようになります。
name: Update Submodule
on:
repository_dispatch:
types: [update]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
submodules: true
- name: Update submodule
run: |
git submodule update --remote ./submod_action_sub/
- name: Git commit
run: |
git config --local user.name "w-haibara"
git config --local user.email "hwhaibarawataru@gmail.com"
git add -A
git status
git commit -m "update submodule (by update_submodule.yml)"
- name: Git push
uses: ad-m/github-push-action@v0.5.0
with:
branch: master
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Main process
run: |
bash ./main.shsubmod_action_main/update_submod.yml at master · w-haibara/submod_action_main · GitHub
やっていることは
Submoduleの更新 --> それに伴う変更をステージング --> 変更をコミット --> メイン処理
という流れです。
ここでは、メイン処理としてシェルスクリプトmain.sh を実行しています。
完成形を試す
さて、完成したシステムを動かしてみます。
初期状態として、submod_action_subには、Helloという文字列が書き込まれたtext.txtが置かれています。
また、submod_action_mainには下記のシェルスクリプトmain.shが置かれています。これは ./submod_action_
sub/text.txtの内容を出力するものです。
#!/bin/bash while read line do echo $line done < ./submod_action_sub/text.txt
まず、submod_action_mainをクローンし、submod_action_subをSubmoduleとして取り込みます。
$ git clone https://github.com/w-haibara/submod_action_main $ cd submod_action_main $ git submodule add https://github.com/w-haibara/submod_action_sub
こうすることで、現時点で最新のsubmod_action_subの内容が取り込まれます。
試しに、main.shを実行すると、現在の./submod_action_sub/text.txtの内容である「Hello」が出力されるはずです。
$ bash ./main.sh Hello
次に、submod_action_subを別にクローンし、text.txtに変更を加えます(「Yeah!」という文字列を書き込みます)。
$ git clone https://github.com/w-haibara/submod_action_sub $ cd submod_action_sub $ echo "Yeah!" > ./text.txt $ git add . $ git commit -m "Update text.txt" $ git push origin master
プッシュを終えたら、Githubでsubmod_action_subのActionsのページを確認します。

API呼び出しのWorkflowが完了しています。
次に、Githubでsubmod_action_mainのActionsのページを確認します。

こちらもWorkflowが完了しているようです。
Workflowの詳細を見てみます。

先ほど書き込んだ「Yeah!」が出力されています!無事にSubmoduleの更新が行われていることを確認できました。