GitHub Composite ActionsでGitHub Pagesにデプロイする
Composite Action
GitHub Actionsを自作する際はDockerコンテナを使う方法[1]やNode.jsで書く方法[2]がありますが、第三の方法としてジョブのstepsの一部を切り出すような形式で書くこともできて、それにはComposite Actionという名前が付いています:
Composite Actionを作成するときのaction.ymlの構文はDockerやJavaScriptの場合とほぼ同じですが、特徴的なのは
-
runs.usingに"composite"を指定すること -
runs.steps[*].runでコマンドを実行するとき、使いたいシェルの種類をruns.steps[*].shellで必ず指定すること
でしょうか。
(action.ymlについての詳細はリファレンスをご覧ください)
利用したいコマンドが環境内に存在することが仮定できてrunの逐次実行だけで済むような処理を共通化して複数のワークフローで使い回したい、という時にComposite Actionを使えば気軽にGitHub Actionを作れて便利そうです。
私はComposite Actionの存在を最近知ったので、何か簡単なお題で練習してみるかと思い、手始めに指定したディレクトリの内容物をGitHub PagesにデプロイするComposite Actionを作ってみました:
https://github.com/pione30/github-pages-deploy-composite-action
2021年10月現在のGitHub-hostedなrunnerの環境ではubuntu-latest、windows-latest、macos-latestともにGitが使える[3][4][5]ので少なくともその環境では動くだろうと思います。
内容としては本当にnaiveな操作しか行っていない簡単なものなのですが、それでも個人的にはそれまで知らなかったGitのコマンドを使ったりしたのでここに記録を残しておきます。
git switch --orphan <new-branch>
このactionを初めて実行したときなど、まだリポジトリにGitHub Pages用のブランチ(gh-pagesとか)が存在していなかった場合には新しくまっさらなブランチをaction内で自動で作成してあげたいわけですが、それって簡単にできるのかなと思って調べたら見つけました。この--orphanオプションをつけてgit switchすると、今までの履歴とは全く無関係な、まるで今git initしたばかりであるかのようなブランチを作成することができます。
ちなみに上記のようにして作成したブランチがリポジトリに存在する場合、そのブランチを普通にgit pullしようとすると
fatal: refusing to merge unrelated histories
Error: Process completed with exit code 128.
というエラーになってしまいます。しかし自分はそんなブランチでも確かな意思をもってpullしたいんだ、というときには--allow-unrelated-historiesという見慣れないオプションをつけてgit pull --allow-unrelated-histories origin gh-pagesのようにしてあげればpullすることができます:
git diff --quiet
Actionを実行した結果、対象となるディレクトリに何も変更が無かった場合はcommitすべき変更も無いわけですが、そんなcleanな状態でgit commitすると
nothing to commit, working tree clean
と表示されつつ終了コードが1となってしまいます。なので変更が無ければその時点で終了コード0でコマンドを終わらせて、変更があった場合のみgit commitやgit pushに進むようにしたいですね。
そこでリファレンスを読んでみると、git diffには--exit-code[6]というオプションがあるようです。これは何らかの変更があれば終了コード1で、変更が無ければ終了コード0でコマンドを終了させるというオプションです。
そしてGitHub Actions上ではdiffの内容をわざわざ表示させる必要はないので--quietオプションを付けたくなりますが、リファレンスを見ると--quietオプションは
Implies
--exit-code
であるようで、まさにぴったりなオプションであることがわかります。したがって
git diff --cached --quiet \
|| git commit -m 'Deploy to GitHub Pages' \
&& git push origin ${{ inputs.branch }}
のように書くことができます。
まとめ
- 基本的なシェルコマンドやコマンドツールの実行だけで済むような処理をGitHub ActionsにしたいときはComposite Actionを試してみるとよさそう
- Gitには便利なオプションが色々あります
-
https://docs.github.com/ja/actions/creating-actions/creating-a-docker-container-action ↩︎
-
https://docs.github.com/ja/actions/creating-actions/creating-a-javascript-action ↩︎
-
https://github.com/actions/virtual-environments/blob/ubuntu20/20210929.1/images/linux/Ubuntu2004-README.md#tools ↩︎
-
https://github.com/actions/virtual-environments/blob/win19/20210928.2/images/win/Windows2019-Readme.md#tools ↩︎
-
https://github.com/actions/virtual-environments/blob/macos-10.15/20201003.1/images/macos/macos-10.15-Readme.md#utilities ↩︎
-
https://git-scm.com/docs/git-diff/2.33.0#Documentation/git-diff.txt---exit-code ↩︎
Discussion