GitHub Actionsでgit submoduleを更新する
GitHub Actionsでsubmoduleを扱う記事は多くありますが、個人でやっている方法についてまとめたいと思います。
submodule自体については、以下の記事がsubmoduleを利用するユースケースなども含めて、かなり分かりやすくまとまっていると思います。
GitHub Actionsの作成
作成したGitHub Actionsですが、ポイントは以下のようになっています。
- actions/checkoutでsubmoduleもHTTPでcloneする
- SSH鍵設定は不要
-
git submodule update --remote --recursive
コマンドで更新する -
cron
で自動実行する -
workflow_dispatch
で手動実行も可能
今回作成したものは以下のリポジトリに置いてあります。
またGitHub Actionsを作成するリポジトリには、既にsubmoduleを追加していることを前提に作成していきます。
actions/checkoutの確認
actions/checkoutのドキュメントを確認します。
普段はおまじないだと思って脳死で書いているところですが、改めて使用方法を確認してみます。
- uses: actions/checkout@v2
with:
snip...
# Whether to checkout submodules: `true` to checkout submodules or `recursive` to
# recursively checkout submodules.
#
# When the `ssh-key` input is not provided, SSH URLs beginning with
# `git@github.com:` are converted to HTTPS.
#
# Default: false
submodules: ''
submodule
と言うパラメータが使用できるとのことなので、submodule: recursive
に設定して使用してみます。
コメントアウトに記載の通り、パラメータssh-key
が設定されていない場合は、
checkoutのステップでsubmoduleもcloneするように設定すると自動的にHTTPでcloneするように切り替わるようです。
.gitmodules
にssh形式で記載されている場合でも適用されます。(勝手に書き変わる事はありません)
git configの設定
git submodule update --remote
は、submoduleをリモートリポジトリの内容に更新するコマンドですが、デフォルトのbranchがmaster
となっています。
これを他のbranchに変更する場合は、ローカルリポジトリで以下を実行します。
: git config -f .gitmodules submodule.<リポジトリ>.branch <ブランチ>
# 例
git config -f .gitmodules submodule.template-gin.branch main
これをsubmodule分だけ実行すると、.gitmodules
ファイルにbranch = main
といった内容が追加されます。(以下は今回のリポジトリにあるものです)
$ cat .gitmodules
[submodule "template-rails"]
path = template-rails
url = git@github.com:ymmmtym/template-rails.git
branch = master
[submodule "template-mkdocs"]
path = template-mkdocs
url = git@github.com:ymmmtym/template-mkdocs.git
branch = main
[submodule "template-deno"]
path = template-deno
url = git@github.com:ymmmtym/template-deno.git
branch = main
[submodule "template-gin"]
path = template-gin
url = git@github.com:ymmmtym/template-gin.git
branch = master
[submodule "template-django-polls"]
path = template-django-polls
url = git@github.com:ymmmtym/template-django-polls.git
branch = master
[submodule "template-vue"]
path = template-vue
url = git@github.com:ymmmtym/template-vue.git
branch = master
[submodule "template-node-express"]
path = template-node-express
url = git@github.com:ymmmtym/template-node-express.git
branch = master
この状態でgit submodule update --remote --recursive
を実行すると、submodule毎に設定されているbranchに対して更新を行うことができます。
workflowの作成
作成したymlは以下になります。
name: Update submodules
on:
schedule:
- cron: '0 * * * *'
workflow_dispatch:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
update_submodules:
name: Update submodules
runs-on: ubuntu-18.04
env:
TZ: "Asia/Tokyo"
if: contains(github.event.head_commit.message, '[ci skip]') == false
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Update submodules
id: update
run: git submodule update --remote --recursive
- name: Run git status
id: status
run: echo "::set-output name=status::$(git status -s)"
- name: Add and commit files
run: |
git add .
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git commit -m "Update submodules at $(date "+DATE: %Y-%m-%d TIME: %H:%M:%S")"
if: ${{ steps.status.outputs.status }}
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: main
if: ${{ steps.status.outputs.status && github.event_name == 'push' }}
やっている内容についてはシンプルになっていて、git status -s
で差分があった場合は、git add .
とgit commit
してmainブランチにpushするworkflowになっています。
デフォルトでは、cronとworkflow_dispatchによってmainブランチで起動したものと、mainブランチにpushされたものが更新され、pushされます。
その他
git submodule foreach git pull origin master
を実行する方法があると知り試しましたが、私の環境では問題点がありました。
まずgit submodule foreach
は全てのsubmoduleに対して、同じgit動作を行うことになります。
なので、mainとmasterなどbranch名が混在する時にはエラーになってしまいます。
repository_dispatch
を利用して、submoduleが更新されたことをトリガーにworkflowを実行できるみたいです。OSS以外をsubmoduleとして導入している場合のベストプラクティスだと感じています。
Reference
Discussion