↩️

【CircleCI】Workflowの自動リトライ機能を試してみた

に公開

はじめに

CircleCIでワークフローが失敗したときに自動で再実行してくれる機能がリリースされました。
https://circleci.com/changelog/automatic-retry-of-workflows-released/

「そもそもワークフローが失敗するときはCIの中で実行しているものが原因だから、再実行してもまた失敗するんじゃないの?」
と思う方もいるかもしれません。

しかし、これはほんの一例に過ぎないのですが、
最近github apiのrate limitの影響により、
公式orbですら普段エラーになったことのない場面でエラーが出るというケースが増えました。

実際にorbのissueで関連した訴えを複数確認出来ています。

【参考】
docker-orbのissue
kubernetes-orbのissue

今回、このような「再実行すれば解決できるかもしれない」というケースにおいて、
workflowのリトライ機能は大変有用であると感じましたので、記事にいたしました。

ご存じなかった方は参考にしていただければ幸いです。

書き方

ワークフローのリトライ設定の書き方は、とても簡単です。
https://circleci.com/docs/guides/orchestrate/automatic-reruns/#quickstart

ワークフローの下に、max_auto_rerunsという設定を1行追加するだけでOKです。

version: 2.1

workflows:
  my-workflow:
    # max_auto_rerunsが追加された
    max_auto_reruns: 3
    jobs:
      - build
      - test
      - deploy:
          requires:
            - build
            - test

制限事項

自動リトライ機能には、以下の制限事項があると記載されています。

  • リトライの最大回数は、ワークフローごとに5回まで
  • 自動リトライは元のワークフローによってのみトリガーされ、手動Runでは自動リトライはトリガーされない
  • パイプラインが 90 日以上経過している場合、自動リトライは無効になる
  • 失敗したワークフローのみが自動リトライをトリガーし、キャンセルされたワークフローはトリガーされない

注意点

自動リトライが実行される毎にコンピューティングクレジットが消費されるので、処理が長いワークフローに対して設定する場合はあらかじめ注意が必要です。

やってみた

自動リトライを入れないパターン

まずは自動リトライを使わずに実行してみましょう。
内容は、一定の確率でJobが失敗するようなシェルスクリプトをコマンドとして呼び出すものです。
生成された乱数が80未満なら「失敗」と判定されるようにしたので、かなり高い確率で失敗するコマンドとなりました。

.circleci/config.yml
version: 2.1

commands:
  sometimes-fail:
    parameters:
      fail-rate:
        type: integer
        default: 80
    steps:
      - run:
          name: "Sometimes Fail"
          command: |
            if [ $((RANDOM % 100)) -lt << parameters.fail-rate >> ]; then
              echo "Failed"
              exit 1
            else
              echo "Succeeded"
            fi

jobs:
  sometimes-fail-job:
    docker:
      - image: cimg/base:stable
    resource_class: small
    steps:
      - checkout
      - sometimes-fail

workflows:
  test:
    jobs:
      - sometimes-fail-job

実行してみると、運良く(?)Failedになりました。
これ以降は当たり前ですが、まだ自動リトライを入れていないため、Failedのまま何も起こりません。
ci01

自動リトライを入れたパターン

今度は先ほどのconfig.ymlmax_auto_rerunsの設定を加えてみます。

.circleci/config.yml
version: 2.1

commands:
  sometimes-fail:
    parameters:
      fail-rate:
        type: integer
        default: 80
    steps:
      - run:
          name: "Sometimes Fail"
          command: |
            if [ $((RANDOM % 100)) -lt << parameters.fail-rate >> ]; then
              echo "Failed"
              exit 1
            else
              echo "Succeeded"
            fi

jobs:
  sometimes-fail-job:
    docker:
      - image: cimg/base:stable
    resource_class: small
    steps:
      - checkout
      - sometimes-fail

workflows:
  test:
    max_auto_reruns: 3
    jobs:
      - sometimes-fail-job

結果はどうでしょうか?

最初がFailed、リトライ1回目と2回目がFailed、そして3回目で運良くSuccessになりましたね。
Auto-rerun N/3という表示が確認できるかとも追います。
つまりmax_auto_reruns: 3は最初の実行とリトライ3で最大4回実行されるという設定になります。
ci02

もし制限を超えたリトライ回数を設定するとどうなる?

もしもmax_auto_rerunsの値を制限の5を超えるとどうなるでしょうか?
念の為試してみました。

workflows:
  test:
    max_auto_reruns: 6
    jobs:
      - sometimes-fail-job

CircleCIのconfigは必ずcommit, pushする前にローカルでvalidateを実行しましょう。

$ circleci config --skip-update-check validate

Error: config compilation contains errors: config compilation contains errors:
        - ERROR IN CONFIG FILE:
        - [#/workflows/test] only 1 subschema matches out of 2
        - 1. [#/workflows/test/max_auto_reruns] 6 is not less or equal to 5
        - |   SCHEMA:
        - |     maximum: 5
        - |   INPUT:
        - |     6

ちゃんと最大は5までだと教えてくれました。
ドキュメントの仕様通りですね。

おわりに

本当に簡単にリトライの設定を入れられるので学習コストも0に等しいくらいで、大変うれしいアップデートだなと感じました。

突然のFailedに悩まされていて、今回の自動リトライが役に立ちそうならどんどん取り入れていきましょう!
ただし、長時間かかるワークフローについては、コストと天秤にかけましょうね。

ここまで読んでいただきありがとうございました。

Discussion