LoginSignup
0

CodeBuildの失敗ビルドを自動的にLambdaで再試行する

Last updated at Posted at 2023-12-03

この記事では、AWS CodeBuildで失敗したビルドを自動的に再試行する例をご紹介します。実務で必要になり、LambdaとEventBridgeで実装したものです。

なお、実務で適用したビルドプロジェクトには、下記のような特徴があります。

  • 毎日早朝にビルドが始まるようスケジューリングしている
  • 開始から完了まで数十分かかる
  • たまに失敗するが、根本的な修正はすぐには難しい
    • 連続して失敗することもある
  • 再試行が翌営業日になっても大きな問題はない

以下、上記の前提を念頭にご覧ください。

EventBridgeで失敗を検知する

さて、まずは、CodeBuildのビルド失敗をEventBridgeで検知します。

EventBridgeルールで、イベントパターンを下記のように指定すると、ビルドプロジェクト project-name のビルド失敗が検知できます。

{
  "source": ["aws.codebuild"],
  "detail-type": ["CodeBuild Build State Change"],
  "detail": {
    "build-status": ["FAILED"],
    "project-name": ["project-name"]
  }
}

イベントパターンの詳細については、公式ドキュメントをご参照ください。

Lambdaで再試行する

続いて、EventBridgeルールのターゲットとなるLambda関数を作成します。下記がコード例です。

import os
import boto3


SUCCESS_CHECK_WINDOW = int(os.getenv("SUCCESS_CHECK_WINDOW", 5))


def lambda_handler(event, context):
    project_name = event["detail"]["project-name"]

    # リトライ条件:
    #   1. 直近のビルドに失敗していること
    #   2. 直近 SUCCESS_CHECK_WINDOW 件のビルドのうち、少なくとも1件に成功していること
    codebuild = boto3.client("codebuild")
    response = codebuild.list_builds_for_project(projectName=project_name)
    builds_detail = codebuild.batch_get_builds(
        ids=response["ids"][:SUCCESS_CHECK_WINDOW]
    )
    if builds_detail["builds"][0]["buildStatus"] == "FAILED" and any(
        b["buildStatus"] == "SUCCEEDED" for b in builds_detail["builds"]
    ):
        response = codebuild.retry_build(id=builds_detail["builds"][0]["id"])
        print(
            f"Rebuild initiated for project '{project_name}' "
            f"with ID '{response['build']['id']}'"
        )

この例では、Lambda関数が同時に複数実行されても1件の再試行に抑えるため、直近のビルドに失敗していること をチェックしています。

また、ビルド失敗の無限ループを避けるため、直近 SUCCESS_CHECK_WINDOW 件のビルドのうち、少なくとも1件に成功していること もチェックしています。SUCCESS_CHECK_WINDOW は環境変数です。

Lambda関数の実行ロールには、CodeBuildアクションの許可が必要です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "codebuild:BatchGetBuilds",
                "codebuild:ListBuildsForProject",
                "codebuild:RetryBuild"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:codebuild:{Region}:{Account ID}:project/project-name"
        }
    ]
}

このLambda関数を、EventBridgeルールのターゲットとして指定すれば、失敗ビルドが自動的に再試行されるようになります。

実務では、ビルド状況をSlackに通知しています。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/notification-rule-create.html

これにより、もしLambdaでの再試行がうまくいかなくても、翌営業日には気づけ、人力で再試行できます。

料金はほとんどかからない

これらを実装するとLambdaの料金が発生します。ただし、微々たるものなので、ほとんどの場合は無視できるでしょう。

おわりに

この記事では、CodeBuildの失敗ビルドを自動的に再試行するために、EventBridgeとLambdaを利用する例をご紹介しました。

実務では、これまで人力で再試行していた手間が省け、担当者に喜んでいただけました。導入から2ヶ月あまりで、人力での再試行は数回だけです。

このように「ちょっとの手間を我慢して担当者が人力対応しているタスク」は探せば色々あると思います。EventBridgeやLambdaをうまく使えば、そのようなタスクが自動化できるかもしれません。

ちなみに、記載したLambda関数のコードは、OpenAIのgpt-4モデルとチャットしながら作ったものでした。関数の目的を伝えたたけで、ほぼ意図どおりのコードが出力されてしまいました。すごい時代ですね。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0