GitHub Actionsで複数Jobが動くWorkflowがあったとして、この最終的な結論を知る方法について調べてみた。
そもそもどうして複数Jobが動くWorkflowの結論が知りたいのかというと、例えば次のようにBuild->Test->Publishのようにシリアルに実行されるJobで構成されるWorkflowがあったとして、最後にその成功・失敗いづれかの結果をSlackで通知したかったから。なお、通知の際は、成功・失敗のステータスを区別する必要があった。
Build Job => Test Job => Publish Job => Slack通知 (成功・失敗いづれも通知)
ダメだった例
まずはダメだった例を紹介する。下記のようにJob群(build、test、publish)と、always()とneedsを使って、それらJob群の結果を取得するJob(slack_notification
)を用意した。 下記の、slack_notificationのように、needsでその前のJobとの依存関係を設定した上で、Job実行条件にalways()を指定することで、その前のJob群がどこかでfailしてスキップされたとしても必ずslack_notificationは実行されるようになる。 ただし、結論からいうと、これは要件を満たさない。slack_notificationの前のJobが成功・失敗関係なく、得られるjob.status
は必ずsuccess
。job.status
とは現在実行中のJobのステータスであるためsuccess
となる。当たり前の話だった。
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: exit 0
test:
runs-on: ubuntu-latest
needs: build
steps:
- run: exit 1
publish:
runs-on: ubuntu-latest
needs: test
steps:
- run: exit 0
slack_notification:
if: always()
needs: publish
runs-on: ubuntu-latest
steps:
- run: |
echo "let's see the workflow conclusion"
echo ${{ job.status }}
このWorkflowの実行結果は下記の通りで、test Jobで失敗しているにも関わらず、slack_notification Jobではステータスをjob.statusから取得しているためsuccess
と表示されてしまっている。
方法1: GitHub API v3 Workflow Jobを使う
GitHub API v3のWorkflow Job APIは、全てのJobの実行結果をconclusion
として返却してくれる。このAPIを上記のslack_notificationでたたけば、そのWorkflowにおいて、それまでのJobの実行結果が成功なのか失敗なのか一覧取得でき、そこから最終結果を判断することが可能となる。
方法2: Workflow Conclusion Actionを使う
方法1で紹介したGitHub API v3のWorkflow Job APIを内部で利用して、Workflow内のJobの結果を全て取得し、その最終結果を環境変数(WORKFLOW_CONCLUSION
)に入れてくれる便利なActionがある。それが、workflow-conclusion-action。正しいJob群の最終結果が得られるので、上記の要件は満たせるわけです。上記のサンプルをworkflow-conclusion-actionをつかって変更すると次のようになる。
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: exit 0
test:
runs-on: ubuntu-latest
needs: build
steps:
- run: exit 1
publish:
runs-on: ubuntu-latest
needs: test
steps:
- run: exit 0
slack_notification:
if: always()
needs: publish
runs-on: ubuntu-latest
steps:
- uses: technote-space/workflow-conclusion-action@v1
- run: |
echo "let's see the workflow conclusion"
echo ${{ env.WORKFLOW_CONCLUSION }}
このWorkflowの実行結果は下記の通り。今度はslack_notification Jobで、ステータスが無事success
と表示された 🎉🎉🎉
まとめると、基本的に、方法1も2もGitHub v3 API Workflow Jobを利用したアプローチ。APIの仕様に準じてパラメータを組み立て、結果をパースすることが苦ではない人は方法1、楽をしたい人は方法2を選択ください。
最後に、slack_notification Jobの中身を、目的のslack通知の内容に書き換えると次のようになる
slack-notification:
if: always()
needs: publish
runs-on: ubuntu-latest
steps:
- uses: technote-space/workflow-conclusion-action@v1
- name: Slack Notification
uses: sonots/slack-notice-action@v3
with:
title: My deployment
status: ${{ env.WORKFLOW_CONCLUSION }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SLACK_WEBHOOK_URL: ${{ secrets.MY_GITHUB_CHANNEL_WEBHOOK }}
本記事で紹介したサンプルコード