TaskCatを使用して、CloudFormationテンプレートのテストを自動化する

TaskCatを使用して、CloudFormationテンプレートのテストを自動化する

TaskCatを使用して、CloudFormationテンプレートのテストを自動化する

以下のAWS公式ページで、CloudFormationテンプレートのテストを自動化する手法が紹介されています。

https://aws.amazon.com/jp/solutions/implementations/taskcat-ci/

この構成の意義について、以下のように説明されています。

この AWS ソリューションは、Amazon Web Services (AWS) クラウド上の AWS CloudFormation 用 TaskCat 継続的統合および継続的デリバリー (CI/CD) パイプラインをデプロイします。TaskCat を使って GitHub リポジトリから CloudFormation テンプレートのテストとデプロイを自動的に行いたいユーザー向けです。

AWS CloudFormation 向け TaskCat CI/CD パイプライン

本ページでは、上記を参考にした構成をご紹介します。
CodeCommit上の開発用ブランチにプッシュされたCloudFormationテンプレートを、TaskCatを使用してテストします。
テストが成功した場合は、パイプラインが継続され、開発用ブランチとマスターブランチをマージします。

構築する環境

Diagram of using TaskCat to automate testing of CloudFormation templates.

CodePipelineでパイプラインを構成します。
パイプラインは以下の流れで動作します。

1つ目はCodeCommitです。
CodeCommitはCodePipelineのソースステージを担当します。
Gitリポジトリとして使用します。
リポジトリにはCloudFormationテンプレートファイル等を保存します。

2つ目はCodeBuildです。
CodeBuildはCodePipelineのビルドステージを担当します。
TaskCatを使用して、テンプレートファイルをテストします。
テスト結果をS3バケットに保存します。

3つ目はSNSです。
SNSはCodePipelineの承認ステージを担当します。
SNS経由でメール通知します。
メール通知を受けたユーザは、パイプラインのページにアクセスし、承認ボタンを押すとパイプラインが再開されます。

4つ目はLambda関数です。
Lambda関数はCodePipelineのデプロイステージを担当します。
この関数の働きは、開発用ブランチとマスターブランチをブランチをマージすることです。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-fa/tree/main/137

テンプレートファイルのポイント解説

CodePipeline

Resources:
  Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      ArtifactStore:
        Location: !Ref ArtifactBucket
        Type: S3
      Name: !Ref Prefix
      RoleArn: !GetAtt CodePipelineRole.Arn
      Stages:
        - Actions:
            - ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: CodeCommit
                Version: 1
              Configuration:
                BranchName: !Ref SourceBranch
                OutputArtifactFormat: CODE_ZIP
                PollForSourceChanges: false
                RepositoryName: !GetAtt CodeCommitRepository.Name
              Name: SourceAction
              OutputArtifacts:
                - Name: !Ref PipelineSourceArtifact
              Region: !Ref AWS::Region
              RunOrder: 1
          Name: Source
        - Actions:
            - ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: 1
              Configuration:
                ProjectName: !Ref CodeBuildProject
              InputArtifacts:
                - Name: !Ref PipelineSourceArtifact
              Name: Build
              OutputArtifacts:
                - Name: !Ref PipelineBuildArtifact
              Region: !Ref AWS::Region
              RunOrder: 2
          Name: Build
        - Actions:
            - ActionTypeId:
                Category: Approval
                Owner: AWS
                Provider: Manual
                Version: 1
              Configuration:
                ExternalEntityLink: !Sub "https://${AWS::Region}.console.aws.amazon.com/s3/buckets/${ArtifactBucket}?region=${AWS::Region}&tab=objects"
                NotificationArn: !Ref TopicArn
              Name: Approval
              Region: !Ref AWS::Region
              RunOrder: 3
          Name: Approval
        - Actions:
            - ActionTypeId:
                Category: Invoke
                Owner: AWS
                Provider: Lambda
                Version: 1
              Configuration:
                FunctionName: !Ref GitMergeFunction
              Name: GitMerge
              Region: !Ref AWS::Region
              RunOrder: 4
          Name: Deploy

  CodePipelineRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - codepipeline.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: PipelinePolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetBucketVersioning
                  - s3:ListBucket
                  - s3:ListBucketVersions
                Resource:
                  - !Sub "arn:aws:s3:::${ArtifactBucket}"
              - Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:PutObject
                Resource:
                  - !Sub "arn:aws:s3:::${ArtifactBucket}/*"
              - Effect: Allow
                Action:
                  - cloudformation:CreateChangeSet
                  - cloudformation:CreateStack
                  - cloudformation:DeleteChangeSet
                  - cloudformation:DeleteStack
                  - cloudformation:DescribeChangeSet
                  - cloudformation:DescribeStacks
                  - cloudformation:ExecuteChangeSet
                  - cloudformation:SetStackPolicy
                  - cloudformation:UpdateStack
                  - cloudformation:ValidateTemplate
                Resource: !Sub "arn:${AWS::Partition}:cloudformation:*:*:*"
              - Effect: Allow
                Action:
                  - iam:PassRole
                Resource: "*"
                Condition:
                  StringEquals:
                    iam:PassedToService: cloudformation.amazonaws.com
              - Effect: Allow
                Action:
                  - codebuild:BatchGetBuilds
                  - codebuild:StartBuild
                Resource: !GetAtt CodeBuildProject.Arn
              - Effect: Allow
                Action:
                  - lambda:invokeFunction
                Resource:
                  - !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${GitMergeFunction}"
              - Effect: Allow
                Action:
                  - codecommit:CancelUploadArchive
                  - codecommit:GetBranch
                  - codecommit:GetCommit
                  - codecommit:GetRepository
                  - codecommit:GetUploadArchiveStatus
                  - codecommit:UploadArchive
                Resource:
                  - !GetAtt CodeCommitRepository.Arn
              - Effect: Allow
                Action:
                  - sns:Publish
                Resource:
                  - !Ref TopicArn
Code language: YAML (yaml)

CodePipelineでパイプラインを作成します。
本パイプラインは4つのステージから構成されています。

ソースステージ

参考サイトではGithubをソースステージとするパイプラインでしたが、今回はCodeCommitを選択します。

BranchNameプロパティに開発用ブランチを指定します。
これによって、同ブランチ上に存在するCloudFormationテンプレートファイル等が、ソースステージのアウトプットアーティファクトとなります。

以下がCodeCommitです。

Resources:
  CodeCommitRepository:
    Type: AWS::CodeCommit::Repository
    Properties:
      RepositoryName: !Ref Prefix
Code language: YAML (yaml)

リポジトリ名だけを指定します。
他は特別な設定を行いません。

ビルドステージ

CodeBuildでCloudFormationテンプレートのテストを実施します。
テスト対象のテンプレートは、ソースステージで生成したアーティファクトです。
具体的には、開発用ブランチ上で管理されている各種ファイルです。

以下がCodeBuildです。

Resources:
  CodeBuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: CODEPIPELINE
      Cache:
        Type: NO_CACHE
      Environment:
        ComputeType: !Ref ProjectEnvironmentComputeType
        EnvironmentVariables:
          - Name: ARTIFACT_BUCKET
            Type: PLAINTEXT
            Value: !Ref ArtifactBucket
          - Name: REGION
            Type: PLAINTEXT
            Value: !Ref AWS::Region
          - Name: REPOSITORY_URL
            Type: PLAINTEXT
            Value: !GetAtt CodeCommitRepository.CloneUrlHttp
          - Name: RELEASE_BRANCH
            Type: PLAINTEXT
            Value: !Ref ReleaseBranch
          - Name: SOURCE_BRANCH
            Type: PLAINTEXT
            Value: !Ref SourceBranch
        Image: !Ref ProjectEnvironmentImage
        ImagePullCredentialsType: CODEBUILD
        Type: !Ref ProjectEnvironmentType
        PrivilegedMode: true
      LogsConfig:
        CloudWatchLogs:
          GroupName: !Ref LogGroup
          Status: ENABLED
        S3Logs:
          Status: DISABLED
      Name: !Sub "${Prefix}-project"
      ServiceRole: !GetAtt CodeBuildRole.Arn
      Source:
        Type: CODEPIPELINE
        BuildSpec: |
          version: 0.2

          env:
            shell: bash

          phases:
            install:
              runtime-versions:
                python: 3.x
              commands:
                - echo "Entered the install phase..."
                - echo "Installing system dependencies..."
                - echo "Installing python dependencies..."
                - pip3 -q install taskcat
            pre_build:
              commands:
                - echo "Entered the pre_build phase..."
                - echo "Current directory is $CODEBUILD_SRC_DIR"
                - ls -lA
                - dirname=`pwd`
                - echo "Directory name $dirname"
                - ls -lA
                - echo "Verifying TaskCat installation..."
                - taskcat
            build:
              commands:
                - echo "Entered the build phase..."
                - echo "Running TaskCat tests..."
                - taskcat test run
                - |
                  if $(grep -Fq "CREATE_FAILED" taskcat_outputs/index.html)
                  then
                    echo "Build failed!"
                    exit 1
                  else
                    echo "Build passed!"
                    exit 0
                  fi
              finally:
                - ls -1 taskcat_outputs
                - ls -1 taskcat_outputs | while read LOG; do cat taskcat_outputs/$LOG; done
                - >- # Do not remove
                  echo "Zipping and uploading report to S3 bucket: '$ARTIFACT_BUCKET'..."
                - zip -r taskcat_report.zip taskcat_outputs
                - aws s3 cp taskcat_report.zip s3://$ARTIFACT_BUCKET/taskcat_reports/$CODEBUILD_BUILD_ID.zip
      Visibility: PRIVATE

  CodeBuildRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - codebuild.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess"
Code language: YAML (yaml)

CodeBuildに関する詳細は以下のページをご確認ください。

あわせて読みたい
CodePipelineにテストユニットを設定する 【CodePipelineにテストユニットを設定する】 CodePipelineにテストユニットを追加することができます。テストユニットはCodeBuildで作成できます。 今回はDockerイメー...

buildspec.ymlがポイントです。

概ねは参考サイトと同様ですが、以下の点が異なります。

  • CodeBuild環境をubuntu系からAmazon Linux系に変更する。
  • Githubからプルしたテンプレートをテストするのではなく、CodeCommit上のものを前ステージからのアーティファクトとしてテストする。
  • pre-commit等はインストールせず、実施もしない。

Taskcatの実行結果をS3バケットに保存します。

承認ステージ

SNS経由でメール通知します。

Resources:
  Topic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !Ref MailAddress
          Protocol: email
      TopicName: !Ref Prefix
Code language: YAML (yaml)

通知先のメールアドレスを指定します。
その他は特別な設定は不要です。

SNSに関する詳細は以下のページをご確認ください。

あわせて読みたい
CFNでSNS入門 – email版 【CFNでSNS入門 - email版】 AWS SNSはメッセージングサービスです。 今回は入門編ということで、通知先にEmailを指定する方法をご紹介します。 【構築する環境】 2種類...

デプロイステージ

Lambda関数を実行して、開発用ブランチとマスターブランチをマージします。

Resources:
  GitMergeFunction:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          REGION: !Ref AWS::Region
          RELEASE_BRANCH: !Ref ReleaseBranch
          REPOSITORY: !GetAtt CodeCommitRepository.Name
          SOURCE_BRANCH: !Ref SourceBranch
      Code:
        ZipFile: |
          import boto3
          import json
          import os

          region = os.environ['REGION']
          release_branch = os.environ['RELEASE_BRANCH']
          repository = os.environ['REPOSITORY']
          source_branch = os.environ['SOURCE_BRANCH']

          codecommit_client = boto3.client('codecommit', region_name=region)
          codepipeline_client = boto3.client('codepipeline', region_name=region)

          def lambda_handler(event, context):
            job_id = event['CodePipeline.job']['id']

            try:
              merge_response = codecommit_client.merge_branches_by_fast_forward(
                repositoryName=repository,
                sourceCommitSpecifier=source_branch,
                destinationCommitSpecifier=release_branch
              )
              print(merge_response)

              codepipeline_client.put_job_success_result(
                jobId=job_id
              )

              return True

            except Exception as e:
              print(e)

              codepipeline_client.put_job_failure_result(
                jobId=job_id,
                failureDetails={
                  'type': 'JobFailed',
                  'message': 'Something happened.'
                }
              )
      FunctionName: !Sub "${Prefix}-GitMergeFunction"
      Handler: !Ref LambdaHandler
      MemorySize: !Ref LambdaMemory
      Runtime: !Ref LambdaRuntime
      Role: !GetAtt GitMergeFunctionRole.Arn
      Timeout: !Ref LambdaTimeout

  GitMergeFunctionRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: GitMergePolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - codecommit:MergeBranchesByFastForward
                Resource: !Sub
                  - "arn:${AWS::Partition}:codecommit:${AWS::Region}:${AWS::AccountId}:${Repository}*"
                  - Repository: !GetAtt CodeCommitRepository.Name
              - Effect: Allow
                Action:
                  - codepipeline:PutJobSuccessResult
                  - codepipeline:PutJobFailureResult
                Resource: "*"
Code language: YAML (yaml)

Lambda関数で実行するコードをインライン表記で定義します。
詳細につきましては、以下のページをご確認ください。

あわせて読みたい
CloudFormationでLambdaを作成する3パータン(S3/インライン/コンテナ) 【CloudFormationでLambdaを作成する】 CloudFormationでLambdaを作成する場合、大別すると以下の3パターンあります。 S3バケットにコードをアップロードする インライ...

参考サイトでは、GithubのエンドポイントにHTTPアクセスしてマージします。
今回はCodeCommitですので、Boto3のCodeCommitクライアントオブジェクトのmerge_branches_by_fast_forwardメソッドを実行して、両ブランチをマージします。

なおCodePipeline内でLambda関数を実行する場合は、CodePipelineクライアントオブジェクトのput_job_success_resultメソッドまたはput_job_failure_resultメソッドを使用する必要があります。
詳細は以下のページをご確認ください。

あわせて読みたい
CodePipelineにLambda関数を呼び出すアクションを定義して、Fargateタスクの希望数を変更する 【CodePipelineにLambda関数を呼び出すアクションを定義して、Fargateタスクの希望数を変更する】 CodePipelineにはさまざまなアクションを設定できますが、今回はパイ...

EventBridge

Resources:
  EventsRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - aws.codecommit
        detail-type:
          - CodeCommit Repository State Change
        resources:
          - !GetAtt CodeCommitRepository.Arn
        detail:
          event:
            - referenceCreated
            - referenceUpdated
          referenceType:
            - branch
          referenceName:
            - !Ref SourceBranch
      Name: !Ref Prefix
      Targets:
        - Arn: !Sub "arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}"
          Id: !Sub "${Prefix}-CodePipeline-CodeCommit"
          RoleArn: !GetAtt EventsRuleRole.Arn

  EventsRuleRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - events.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: PipelineExecutionPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - codepipeline:StartPipelineExecution
                Resource:
                  - !Sub "arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}"
Code language: YAML (yaml)

EventBridgeを使用して、CodePipelineの開始をトリガーします。

以下のページを参考に、EventBridgeルールおよびIAMロールを作成します。

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/update-change-detection.html#update-change-detection-cfn-codecommit

具体的には、開発用ブランチで作成・更新のイベントを検出した場合、トリガーします。

(参考)テストテンプレート

AWSTemplateFormatVersion: 2010-09-09

Parameters:
  Handler:
    Type: String

  Memory:
    Type: Number

  Prefix:
    Type: String

  Runtime:
    Type: String


Resources:
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          REGION: !Ref AWS::Region
          MEMORY: !Ref Memory
      Code:
        ZipFile: |
          import json
          import os

          region = os.environ['REGION']
          memory = os.environ['MEMORY']

          def lambda_handler(event, context):
            data = {
              'region': region,
              'memory': memory
            }

            return {
              'statusCode': 200,
              'body': json.dumps(data, indent=2)
            }
      FunctionName: !Sub "${Prefix}-function"
      Handler: !Ref Handler
      MemorySize: !Ref Memory
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn

  Function2:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          REGION: !Ref AWS::Region
          MEMORY: !Ref Memory
      Code:
        ZipFile: |
          import json
          import os

          region = os.environ['REGION']
          memory = os.environ['MEMORY']

          def lambda_handler(event, context):
            data = {
              'region': region,
              'memory': memory
            }

            return {
              'statusCode': 200,
              'body': json.dumps(data, indent=2)
            }
      FunctionName: !Sub "${Prefix}-function2"
      Handler: !Ref Handler
      MemorySize: !Ref Memory
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn

  FunctionRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Code language: YAML (yaml)

サンプルのCloudFormationテンプレートです。
Taskcatでテストする対象です。

Lambda関数およびIAMロールを作成する内容です。

.taskcat.yml

project:
  name: taskcat-ci
  regions:
    - ap-northeast-1
tests:
  default:
    parameters:
      Handler: index.lambda_handler
      Memory: 128
      Prefix: taskcat-ci
      Runtime: python3.8
    template: ./test-template.yaml
Code language: YAML (yaml)

Taskcatの設定ファイルです。

テスト対象として先述のテンプレートを指定します。
テストスタックはap-northeast-1リージョンに作成します。
parametersでテストスタック作成時のパラメータを指定します。
今回は4つのパラメータを渡します。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • CodePipeline:fa-137
  • CodeCommitリポジトリ:fa-137
  • CodeBuildプロジェクト:fa-137
  • S3バケット:fa-137
  • Lambda関数:fa-137-GitMergeFunction
  • SNSトピック:fa-137

メールアドレスの認証

SNSトピックのサブスクライバーとしてメールアドレスを指定した場合、そのメールアドレスを認証する必要があります。
指定したメールアドレスに、以下のような認証メールが送られてきます。

Detail of SNS 1.

「Confirm subscription」を押下して、認証を進めます。

Detail of SNS 2.

上記のページが表示されて、認証が完了したことがわかります。

リソース確認

作成されたリソースをAWS Management Consoleから確認します。

SNSを確認します。

Detail of SNS 3.

確かにSNSトピックが作成されています。

CodeCommitを確認します。

Detail of CodeCommit 1.

確かにリポジトリが作成されています。

CodeBuildを確認します。

Detail of CodeBuild 1.

確かにCodeBuildプロジェクトが作成されています。

Lambda関数を確認します。

Detail of Lambda 1.

正常に作成されています。

CodePipelineを確認します。

Detail of CodePipeline 1.

パイプラインの実行に失敗しています。
これはCloudFormationスタック作成時に、CodeCommitが作成されたことがきっかけとして、パイプラインが実行されたためです。
現時点ではCodeCommitにコードをプッシュしていないため、パイプライン実行の過程でエラーが発生しました。

動作確認

準備が整いましたので、CodeCommitにコードをプッシュします。

まずCodeCommitリポジトリをプルします。

$ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/fa-137
Cloning into 'fa-137'...
warning: You appear to have cloned an empty repository.Code language: Bash (bash)

空のリポジトリがプルされました。

マスターブランチをコミット・プッシュします。

(master) $ git commit --allow-empty -m "initial commit"
[master (root-commit) 3aee162] initial commit
...

(master) $ git push
...
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/fa-137
 * [new branch]      master -> master
...Code language: Bash (bash)

ファイルは存在しませんが、コミット・プッシュしました。
後述の開発用ブランチの作成や、両ブランチをマージするために必要な手続きです。

開発用ブランチを作成します。

(master) $ git branch dev

(master) $ git branch -a
  dev
* master
  remotes/origin/masterCode language: Bash (bash)

開発用ブランチに切り替えます。

(master) $ git checkout dev
Switched to branch 'dev'Code language: Bash (bash)

テスト用のテンプレートやTaskcat用ファイルを配置します。

(dev) $ ls -al
total 8
drwxrwxr-x 3 ec2-user ec2-user   64 Jul  7 11:56 .
drwxrwxr-x 3 ec2-user ec2-user   20 Jul  7 11:43 ..
drwxrwxr-x 8 ec2-user ec2-user  166 Jul  7 11:55 .git
-rw-rw-r-- 1 ec2-user ec2-user  264 Jul  4 23:12 .taskcat.yml
-rw-rw-r-- 1 ec2-user ec2-user 3426 Jul  7 11:26 test-template.yamlCode language: Bash (bash)

2ファイルを開発用ブランチにプッシュします。

(dev) $ git add .

(dev) $ git commit -m 'first commit'
[dev 8fee41a] first commit
...
 2 files changed, 146 insertions(+)
 create mode 100644 .taskcat.yml
 create mode 100644 test-template.yaml

(dev) $ git push --set-upstream origin dev
...
To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/fa-137
 * [new branch]      dev -> dev
branch 'dev' set up to track 'origin/dev'.Code language: Bash (bash)

正常にプッシュできました。

改めてCodeCommitを確認します。

Detail of CodeCommit 2.

確かに2ファイルがプッシュされています。

CodePipelineを確認します。

Detail of CodePipeline 2.

CodePipelineが開始されました。
CodeCommitの開発用ブランチが更新されたことがきっかけです。

Sourceステージが完了しました。
続いてBuildステージが開始されています。

しばらく待つとCodeBuildが正常に完了し、Buildステージも終了します。

Detail of CodeBuild 2.
Detail of CodePipeline 3.

Approvalステージで一時停止しています。

SNSトピックに指定したメールアドレスに、以下のようなメッセージが届きました。

Detail of SNS 4.

承認するためのレビューを行います。

「Content to review」のURLにアクセスします。

Detail of S3 1.

ZIPファイルが保存されています。

中身を確認します。

Detail of S3 2.
Detail of S3 3.

Taskcatによるテスト結果です。
CloudFormationによって、ap-northeast-1リージョンにLambda関数とIAMロールが正常に生成できました。

テンプレートに問題ないことが確認できましたので、承認アクションを実行します。

Detail of CodePipeline 4.

これでパイプラインが再開されます。

しばらく待つと、Deployステージも完了します。

Detail of CodePipeline 5.

Lambda関数の実行ログを確認します。

Detail of Lambda 2.

正常に実行されたことがわかります。
つまり開発用ブランチとマスターブランチのマージが正常に実行されたということです。

最後にCodeCommitを確認します。

Detail of CodeCommit 3.

開発用ブランチに加えて、マスターブランチにもコミットされた形跡があります。

Detail of CodeCommit 4.

マスターブランチに2ファイルが格納されています。
つまり2ブランチがマージされたことによって、開発用ブランチにあったファイルがマスターブランチにも置かれました。

まとめ

CodeCommit上の開発用ブランチにプッシュされたCloudFormationテンプレートを、TaskCatを使用してテストしました。
テストが成功した場合は、パイプラインが継続され、開発用ブランチとマスターブランチをマージしました。