CircleCI では、処理の途中でエラーが検出されると、後続処理は実行されず、CI がそこで中断してしまいます。CI の多くは、そのような挙動であると思いますが、ここでは途中でエラーが発生しても、処理を最後まで継続して、最後にエラーを報告する方法について書いてみます。
表現に迷ったのですが、クロージング、Finally、Teardown そういった感じの、最後にかならず実行される処理を表現する方法についてです。
環境
- CircleCI 2.0 (2017-07-30 執筆時点)
書き方
書き方さえ分かってしまえば難しくないので、最初に書き方から。
version: 2
jobs:
build:
machine: true
steps:
- run:
name: 後始末をしなければならない処理
command: |
# ACL 変更など
- run:
name: エラーで終了する可能性のある処理(1)
command: |
command_not_found || echo "export TEST_RESULT_1=${?}" >> $BASH_ENV
- run:
name: エラーで終了する可能性のある処理(2)
command: |
command_not_found || echo "export TEST_RESULT_2=${?}" >> $BASH_ENV
- run:
name: 後始末の処理
command: |
# ACL 変更のなど
- run:
name: エラー報告
command: |
echo "TEST_RESULT_1 [${TEST_RESULT_1:-0}]"
echo "TEST_RESULT_2 [${TEST_RESULT_2:-0}]"
exit $(expr ${TEST_RESULT_1:-0} + ${TEST_RESULT_2:-0})
解説
CircleCI 2.0 では、run
のなかで表現された各行のいずれかが 、exit 0
以外を返す場合に、CI を中断し、エラーを報告します。最終行が exit 0
だったとしても、途中でエラーが発生していたら、その時点で中断されます。
そのため、エラーで終了する可能性のある処理については必ず、エラーで終了しないよう、ハンドリングを施す必要があります。ここでハンドリングと表現しているのは以下です。
|| echo "export TEST_RESULT_1=${?}" >> $BASH_ENV
直前のコマンドを OR でつなぐことにより、行を終了させず、処理を継続しています。
また CircleCI 2.0 では、run
をまたぐと、作成した変数などが共有されず、参照することができません。一方、各 run
の最初では、$BASH_ENV
が自動的に展開されるため、ここに退避しておくことで、後続処理から参照したい変数などを残しておくことができます。
今回は、途中で発生したエラーを最後に報告したいので、これを $BASH_ENV
に退避しています。
以上のように CircleCI 2.0 では、一手間を加えるだけで、エラー報告を最後に回して、クロージングが必要な処理も比較的簡単に表現できるようになっています。
参考