注意
2020/02/08追記
この記事はGitHub Actions v1の話で、今のv2とは全く違う内容になっておりますm(_ _)m
エラーハンドリングについてもv2になってからはif: failure()
とかで失敗時にタスクを実行みたいな設定が出来るようになりました!これでSlack通知のためにエラーハンドリングをしなくて良くなりました^^
始めに
今までCircleCIやCodeBuildを使ってきましたが、最近GitHubアクションも使ってみました。その際にエラー通知を実装しようとしたらかなり苦戦してしまったためそれについて記事にしました。
エラーハンドリングする術がない
GitHubアクションのステータスはWeb上では確認でき、check_suite
などのイベントでフックできると書いてあります。
push
イベントでビルドとデプロイを実行し、check_suite
でステータスをみてSlack通知する方法を考えていたのですが、なぜかcheck_suite
のイベントはフックされませんでした。
結論から言うとGitHubアクションで実行した処理はイベントのフック対象にはならないです。push
イベントでgh-pagesブランチにpushしても再度push
イベントはフックされないといった感じです。
アクションが失敗した場合は次のアクションは実行されませんので、エラーをハンドリングする方法はないと思った方が良さそうです。
ちなみにcheck_suite
は他のCIを実行した時にイベントをハンドリングすることはできました(あんまり意味がない気がしますが・・・)
それでもエラーハンドリングをしたい場合
アクションを順番に実行するとエラーハンドリングできなくなってしまうので、一つのアクションで全部書くしかないかなと思っています。
僕は以下のようにアクションを自前で定義してそれだけを呼ぶようにしています。自前でshellを書くとtrapを使ってtry-catchっぽくかけるので、それで成功とエラー通知をすることができます。
workflow "Build and Deploy" {
on = "push"
resolves = ["main"]
}
action "main" {
uses = "./.github/action/"
secrets = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]
}
# !/bin/bash
# ========== メソッドとエラーハンドリングの設定 ===========
# Slack通知メソッド
function notify() {
if [ $1 = "SUCCESS" ]; then
STATUS_COLOR="good"
STATUS_TEXT="SUCCESS"
else
STATUS_COLOR="danger"
STATUS_TEXT="FAILED"
fi
JSON=$(cat << EOS
{
"attachments": [
{
"title": "${GITHUB_REPOSITORY}",
"title_link": "${ACTION_URL}",
"color": "${STATUS_COLOR}",
"fields": [
{ "title": "STATUS", "value": "${STATUS_TEXT}", "short": "true" }
]
}
]
}
EOS
)
RES=`curl -s -X POST -H 'Content-Type: application/json' -d "${JSON}" ${SLACK_WEBHOOK_API_URL}`
echo $RES
}
# catchメソッド
function catch() {
notify ERROR
}
# エラーした時にcatchメソッドを呼ぶように設定
set -e
trap catch ERR
# ========== メイン処理 ==========
# Slack通知のURL
SLACK_WEBHOOK_API_URL=[WebHook URL]
# ActionのURL
ACTION_URL=https://github.com/$GITHUB_REPOSITORY/actions
# インストールとビルド
yarn install
yarn build
# S3にアップロード
aws s3 sync ./dist/ s3://bucket-name --exact-timestamps --delete
# Slackに成功を通知する
notify SUCCESS
終わりに
GitHubアクションはやり方が分かると結構使いやすそうな印象でしたが、エラーハンドリングはかなり厳しそうでした。エラーハンドリングをするなら他のアクションを使うのはほぼ無理な気がしました。
小さなモジュールを組み合わせていくという発想は良さそうに見えますが、その分毎回Dockerの起動をさせられてオーバーヘッドがかかったり、ちょっとした文字列加工をしてもその変数を引き継ぐ術がなかったり、細かいことをやろうとすると結構やりづらかったです。
こういった問題はアクションを自作して一つのshellにしてしまえば解決するのですが、GitHubアクションの特徴を殺してしまっている気がしてならないですね・・・。