Amazon Web Services ブログ

新機能 – Step Functions と AWS CodeBuild を使用した継続的インテグレーションワークフローの構築



ソフトウェアビルドの自動化は、DevOps のベストプラクティスを採用するための重要なステップです。これを支援するために、フルマネージド型の継続的インテグレーションサービスである AWS CodeBuild を構築しました。これは、ソースコードをコンパイルし、テストを実行し、デプロイの準備ができたパッケージを生成します。

しかし、お客様のビルドプロセスには非常に多くのカスタマイズの選択肢があり、ソフトウェアビルドに必要なさまざまなアクティビティを調整するために、開発者が独自のカスタムワークフローを作成することに時間を費やしていることがわかりました。たとえば、一部のテストを実行し、もしくは実行しないこととし、またはクイックフィックスをデプロイする必要がある場合にコードの静的分析をスキップしたい場合があります。 単体テストの結果に応じて、さまざまなアクションを実行したり、SNS を介して通知を受けたりしたい場合があります。

これを簡素化するため、本日、新しい AWS Step FunctionsCodeBuild とのサービス統合をリリースします。これで、ステートマシンの実行中に、ビルドの開始または停止ビルドレポートサマリーの取得、および過去のビルド実行レコードの削除ができるようになります。

これにより、独自のワークフロー主導のビルドプロセスを定義し、手動または自動でトリガーできます。たとえば、次のことができます。

この統合により、Step Functions の全機能を使用して、ソフトウェアのビルドを自動化できます。たとえば、Parallel 状態を使用して、ビルドの独立したコンポーネントの並列ビルドを作成できます。コードリポジトリ内のすべてのブランチのリストから始めて、Map 状態を使用して、各ブランチに一連のステップ (自動化ビルド、ユニットテスト、統合テスト) を実行できます。 同じワークフローで他の Step Functions のサービス統合を活用することもできます。 たとえば、メッセージを SQS キューに送信してアクティビティを追跡したり、Amazon ECSAWS Fargate を使用して構築したコンテナ化されたアプリケーションを開始したりできます。

ワークフロー主導のビルドプロセスのために Step Functions を使用する
Java ウェブアプリケーションに取り組んでいます。追加する新しい機能が確実に機能するように、JUnit Jupiter を使用していくつかのテストを作成しました。ビルドプロセスの直後にこれらのテストを実行したいのですが、テストがいくつかの迅速なイテレーションを遅くする可能性があるため、常に実行したいとは限りません。テストを実行するとき、CodeBuild を使用してテストのレポートを保存および表示したいと考えています。最後に、テストが実行され、成功した場合は、SNS トピックで通知を受け取りたいと考えています。

CodeCommit でリポジトリを作成し、CodeBuild 用に 2 つの buildspec ファイルを含めました。

  • buildspec.yml がデフォルトで、Apache Maven を使用してビルドとテストを実行し、テスト結果をレポートとして保存しています。
version: 0.2
phases:
  build:
    commands:
      - mvn package
artifacts:
  files:
    - target/binary-converter-1.0-SNAPSHOT.jar
reports:
  SurefireReports:
    files:
      - '**/*'
    base-directory: 'target/surefire-reports'
  • buildspec-notests.yml はビルドのみを実行します。実行されるテストはありません。
version: 0.2
phases:
  build:
    commands:
      - mvn package -DskipTests
artifacts:
  files:
    - target/binary-converter-1.0-SNAPSHOT.jar

CodeBuild のプロジェクトと Step Functions のステートマシンをセットアップしてビルドを自動化するために、AWS CloudFormation と次のテンプレートを使用しています。

AWSTemplateFormatVersion: 2010-09-09
Description: AWS Step Functions sample project for getting notified on AWS CodeBuild test report results
Resources:
  CodeBuildStateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      RoleArn: !GetAtt [ CodeBuildExecutionRole, Arn ]
      DefinitionString:
        !Sub
          - |-
            {
              "Comment": "An example of using CodeBuild to run (or not run) tests, get test results and send a notification.",
              "StartAt": "Run Tests?",
              "States": {
                "Run Tests?": {
                  "Type": "Choice",
                  "Choices": [
                    {
                      "Variable": "$.tests",
                      "BooleanEquals": false,
                      "Next": "Trigger CodeBuild Build Without Tests"
                    }
                  ],
                  "Default": "Trigger CodeBuild Build With Tests"
                },
                "Trigger CodeBuild Build With Tests": {
                  "Type": "Task",
                  "Resource": "arn:${AWS::Partition}:states:::codebuild:startBuild.sync",
                  "Parameters": {
                    "ProjectName": "${projectName}"
                  },
                  "Next": "Get Test Results"
                },
                "Trigger CodeBuild Build Without Tests": {
                  "Type": "Task",
                  "Resource": "arn:${AWS::Partition}:states:::codebuild:startBuild.sync",
                  "Parameters": {
                    "ProjectName": "${projectName}",
                    "BuildspecOverride": "buildspec-notests.yml"
                  },
                  "Next": "Notify No Tests"
                },
                "Get Test Results": {
                  "Type": "Task",
                  "Resource": "arn:${AWS::Partition}:states:::codebuild:batchGetReports",
                  "Parameters": {
                    "ReportArns.$": "$.Build.ReportArns"
                  },
                  "Next": "All Tests Passed?"
                },
                "All Tests Passed?": {
                  "Type": "Choice",
                  "Choices": [
                    {
                      "Variable": "$.Reports[0].Status",
                      "StringEquals": "SUCCEEDED",
                      "Next": "Notify Success"
                    }
                  ],
                  "Default": "Notify Failure"
                },
                "Notify Success": {
                  "Type": "Task",
                  "Resource": "arn:${AWS::Partition}:states:::sns:publish",
                  "Parameters": {
                    "Message": "CodeBuild build tests succeeded",
                    "TopicArn": "${snsTopicArn}"
                  },
                  "End": true
                },
                "Notify Failure": {
                  "Type": "Task",
                  "Resource": "arn:${AWS::Partition}:states:::sns:publish",
                  "Parameters": {
                    "Message": "CodeBuild build tests failed",
                    "TopicArn": "${snsTopicArn}"
                  },
                  "End": true
                },
                "Notify No Tests": {
                  "Type": "Task",
                  "Resource": "arn:${AWS::Partition}:states:::sns:publish",
                  "Parameters": {
                    "Message": "CodeBuild build without tests",
                    "TopicArn": "${snsTopicArn}"
                  },
                  "End": true
                }
              }
            }
          - {snsTopicArn: !Ref SNSTopic, projectName: !Ref CodeBuildProject}
  SNSTopic:
    Type: AWS::SNS::Topic
  CodeBuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      ServiceRole: !Ref CodeBuildServiceRole
      Artifacts:
        Type: NO_ARTIFACTS
      Environment:
        Type: LINUX_CONTAINER
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/standard:2.0
      Source:
        Type: CODECOMMIT
        Location: https://git-codecommit.us-east-1.amazonaws.com/v1/repos/binary-converter
  CodeBuildExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action: "sts:AssumeRole"
            Principal:
              Service: states.amazonaws.com
      Path: "/"
      Policies:
        - PolicyName: CodeBuildExecutionRolePolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "sns:Publish"
                Resource:
                  - !Ref SNSTopic
              - Effect: Allow
                Action:
                  - "codebuild:StartBuild"
                  - "codebuild:StopBuild"
                  - "codebuild:BatchGetBuilds"
                  - "codebuild:BatchGetReports"
                Resource: "*"
              - Effect: Allow
                Action:
                  - "events:PutTargets"
                  - "events:PutRule"
                  - "events:DescribeRule"
                Resource:
                  - !Sub "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/StepFunctionsGetEventForCodeBuildStartBuildRule"
  CodeBuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action: "sts:AssumeRole"
            Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
      Path: /
      Policies:
        - PolicyName: CodeBuildServiceRolePolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                - "logs:CreateLogGroup"
                - "logs:CreateLogStream"
                - "logs:PutLogEvents"
                - "codebuild:CreateReportGroup"
                - "codebuild:CreateReport"
                - "codebuild:UpdateReport"
                - "codebuild:BatchPutTestCases"
                - "codecommit:GitPull"
                Resource: "*"
Outputs:
  StateMachineArn:
    Value: !Ref CodeBuildStateMachine
  ExecutionInput:
    Description: Sample input to StartExecution.
    Value:
      >
        {}

CloudFormation スタックが作成されると、ステートマシン定義に 2 つの CodeBuild タスクが存在することになります。

  • 最初の CodeBuild タスクは、同期統合 (startBuild.sync) を使用して、ビルドが終了するまで自動的に待機してから、次のステップに進みます。
"Trigger CodeBuild Build With Tests": {
  "Type": "Task",
  "Resource": "arn:aws:states:::codebuild:startBuild.sync",
  "Parameters": {
    "ProjectName": "CodeBuildProject-HaVamwTeX8kM"
  },
  "Next": "Get Test Results"
}
  • 2 つ目の CodeBuild タスクは、BuildspecOverride パラメータを使用して、ビルドで使用されるデフォルトの buildspec ファイルを、テストを実行していないファイルでオーバーライドします。
"Trigger CodeBuild Build Without Tests": {
  "Type": "Task",
  "Resource": "arn:aws:states:::codebuild:startBuild.sync",
  "Parameters": {
    "ProjectName": "CodeBuildProject-HaVamwTeX8kM",
    "BuildspecOverride": "buildspec-notests.yml"
  },
  "Next": "Notify No Tests"
},

最初のステップは Choice です。これは、ステートマシン実行の入力を調べて、テストを実行するかどうかを決定するものです。たとえば、以下を入力して、テストを実行します。

{
  "tests": true
}

これは、テストを実行する視覚的な実行ワークフローです。すべてのテストに合格しています。

[tests] の値を false に変更し、別のブランチでの新しい実行を開始します。

今回、buildspec はテストを実行しておらず、実行されたテストがなかった旨の通知が表示されます。

GitHub または CodeCommit でのアクティビティの後でこのワークフローを自動で開始すると、特定のパターンの最後のコミットメッセージを調べて、それに応じてビルドプロセスをカスタマイズできます。たとえば、[skip tests] 文字列がコミットメッセージの一部である場合、テストをスキップできます。同様に、本番環境では、[skip static analysis] メッセージがコミットに含まれている場合、コードの静的分析をスキップして、緊急の変更のための統合を迅速化できます。

コンテナ化されたアプリケーションのワークフローを拡張する
アプリケーションをさまざまな環境に配布する優れた方法は、アプリケーションを Docker イメージとしてパッケージ化することです。この方法により、ビルドワークフローにステップを追加し、品質保証 (QA) チームのために Amazon ECS タスク (AWS Fargate で実行) でコンテナ化されたアプリケーションを開始することもできます。

最初に、ECR にイメージリポジトリを作成し、こちらで説明するように、ECR にアップロードするために CodeBuild のプロジェクトで使用されるサービスロールにアクセス許可を追加します。

次に、コードリポジトリで、この例に従って追加します。

  • ソフトウェアビルドで Docker コンテナを準備し、アプリケーションを起動するための Dockerfile
  • Docker イメージを作成およびアップロードするコマンドを含む buildspec-docker.yml ファイル。

最終的なワークフローは、次のすべてのステップを自動化します。

  1. ソースコードからソフトウェアを構築します。
  2. Docker イメージを作成します。
  3. ECR に Docker イメージをアップロードします。
  4. ECS および Fargate での QA 環境を開始します。
  5. QA 環境の準備ができている旨の SNS 通知を送信します。

ワークフローとそのステップは、要件に基づいて簡単にカスタマイズできます。たとえば、いくつかの変更を加えるだけで、buildspec ファイルを適用してイメージを Docker Hub にプッシュできます

今すぐ利用可能
CodeBuild のサービス統合は、Step Functions および CodeBuild サービスが提供されているすべての商用および GovCloud リージョンで利用できます。リージョンごとの利用の可否については、AWS リージョン表をご覧ください。 詳細については、ドキュメントをご覧ください

AWS サーバーレスヒーローである Gojko Adzic 氏AWS DevOps ブログで指摘したように、CodeBuild を使用して管理タスクを実行することもできますStep Functions との統合により、一連の新しい可能性が開かれます。

これらの新しいサービス統合を皆さんがどのように活用しているか、ぜひお知らせください!

Danilo