こんにちは。SCSKのふくちーぬです。
皆さんは、イベントベースのCodePipelineのパイプラインを利用していますでしょうか。それともポーリングベースのパイプラインを利用していますでしょうか。
まだポーリングベースを利用している方は、本記事を読んでいただきイベントベースへの移行をしていただけると幸いです。(ふくちーぬもその内の1人でした。。)
本記事では、以下のAWS公式ドキュメントに従いCodeCommitをソースとしたCloudFormationで構築済みのポーリングベースのCodepipelineからイベントベースへの移行を実施します。
CodePipelineの検出オプションの種類
CodePipelineには、ソースの検出オプションとしてポーリングベース・イベントベースの2種類があります。
ポーリングベースでは、CodePipelineがCodeCommit内の対象ブランチに対して定期的に監視することで、変更を検出しています。
イベントベースでは、対象ブランチに変更があった際にEventBridgeにイベントを送信するだけです。すなわちCodePipelineは、どんと構えてEventBridgeからのメッセージを待っていればよいだけです。
ポーリングベースのパイプラインの移行を推奨している件
2023年4月下旬に、AWS サポートから以下のようなメールが届きました。
本メッセージは、1つ以上ポーリングパイプラインをお持ちのお客様にお送りしています。ポーリングパイプラインは、変更をポーリングするように設定されたソースアクションが少なくとも1つあるパイプラインとして定義されます。AWS CodePipelineチームは、2023年5月25日より、非アクティブなパイプラインでのポーリングを無効にします。非アクティブなパイプラインとは、過去30日間にパイプラインの実行が開始されていないパイプラインと定義されます。Amazon EventBridgeルール、AWS CodeStar接続、またはウェブフックのみを使用してパイプラインをトリガーする非アクティブなパイプラインは影響を受けません。また、アクティブなパイプラインも影響を受けません。
ソースのトリガーメカニズムとして、Amazon EventBridge、AWS CodeStar接続、またはウェブフックを使用するように更新することをお勧めします。
つまり、「30日以上利用されていないポーリングベースのパイプラインを無効にする」、「ポーリングベースのパイプラインを移行することを推奨する」のアナウンスをしています。
現時点でも、ポーリングベースのパイプラインを新規に作成することはできます。また無効になったパイプラインも手動で実行することで、パイプラインを起動することは可能です。
推測ですが、AWS的にCodePipelineがポーリングするコストが割りに合っていないことも要因の1つかもしれませんね。
イベントベースのパイプラインを推奨する理由
- ソースリポジトリのブランチの変更を迅速に検出できるようになり、パイプライン実行パフォーマンスが向上する
CI/CDパイプラインの準備
Cloud9の作成
以下に AWS Cloud9 の作成方法を記載しているので参考にしてください。
Cloud9とCodeCommitの連携
Cloud9からCodeCommitにプッシュできるように準備してください。
CodeCommitへのソースコード配置
今回の検証ではCodeCommitに配置するものは任意のもので問題ありませんが、以下を利用することにします。
CI/CDパイプラインの作成
ご使用のAWSアカウント内にポーリングベースのパイプラインがCloudFormationにて作成済みの方は、それをご利用ください。
今回は、新規にポーリングベースのパイプラインを作成した後に、イベントベースへ移行します。
ポーリングベースのパイプラインの作成
ポイントはパイプラインの定義にて、”PollForSourceChanges”を”true”に設定することでポーリングベースのパイプラインを作成できます。
以下のCloudFormationテンプレートをデプロイして、ポーリングベースのパイプラインを構築してください。
AWSTemplateFormatVersion: 2010-09-09
Description: cfn CI/CD Pipeline
Parameters:
ResourceName:
Type: String
REPOSITORYNAME:
Type: String
Description: aws codecommit repository name
STACKNAME:
Type: String
MailAddress:
Type: String
Resources:
ArtifactStoreBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub s3bucket-${AWS::AccountId}-artifactbucket
CodeBuildBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub s3bucket-${AWS::AccountId}-codebuildtbucket
# ------------------------------------------------------------#
# CodeBuild Role (IAM)
# ------------------------------------------------------------#
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Path: /
ManagedPolicyArns:
- !Ref CodeBuildPolicy
- arn:aws:iam::aws:policy/AWSCloudFormationFullAccess
RoleName: !Sub "IRL-CODEBUILD-S3CloudWatchlogsAccess"
# ------------------------------------------------------------#
# CodeBuild Role Policy (IAM)
# ------------------------------------------------------------#
CodeBuildPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: CodeBuildAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: CloudWatchLogsAccess
Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*
- Sid: S3Access
Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:GetObjectVersion
Resource:
- !Sub arn:aws:s3:::${ArtifactStoreBucket}
- !Sub arn:aws:s3:::${ArtifactStoreBucket}/*
- !Sub arn:aws:s3:::${CodeBuildBucket}
- !Sub arn:aws:s3:::${CodeBuildBucket}/*
- Sid: IAMPass
Effect: Allow
Action:
- iam:PassRole
Resource: "*"
- Sid: CloudFormationAccess
Effect: Allow
Action: cloudformation:ValidateTemplate
Resource: "*"
# ------------------------------------------------------------#
# CodeBuild linter Project
# ------------------------------------------------------------#
CodeBuildProjectLint:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${ResourceName}-project-lint
ServiceRole: !GetAtt CodeBuildRole.Arn
Artifacts:
Type: CODEPIPELINE
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
EnvironmentVariables:
- Name: AWS_REGION
Value: !Ref AWS::Region
- Name: S3_BUCKET
Value: !Ref CodeBuildBucket
Source:
Type: CODEPIPELINE
# ------------------------------------------------------------#
# CodeBuild changeset Project
# ------------------------------------------------------------#
CodeBuildProjectChangeset:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${ResourceName}-project-changeset
ServiceRole: !GetAtt CodeBuildRole.Arn
Artifacts:
Type: CODEPIPELINE
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
EnvironmentVariables:
- Name: AWS_REGION
Value: !Ref AWS::Region
- Name: S3_BUCKET
Value: !Ref CodeBuildBucket
- Name: STACK_NAME
Value: !Ref STACKNAME
- Name: CFNROLE_ARN
Value: !GetAtt CloudformationRole.Arn
Source:
Type: CODEPIPELINE
BuildSpec: changeset-buildspec.yaml
# ------------------------------------------------------------#
# CloudFormation Role (IAM)
# ------------------------------------------------------------#
CloudformationRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service: cloudformation.amazonaws.com
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
RoleName: "IRL-CLOUDFORMATION-ServiceFullAccess"
# ------------------------------------------------------------#
# CodePipeline Role (IAM)
# ------------------------------------------------------------#
PipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Path: /
ManagedPolicyArns:
- !Ref PipelinePolicy
RoleName: "IRL-CODEPIPELINE-Access"
# ------------------------------------------------------------#
# CodePipeline Role Policy (IAM)
# ------------------------------------------------------------#
PipelinePolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: CodePipelineAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: S3FullAccess
Effect: Allow
Action: s3:*
Resource:
- !Sub arn:aws:s3:::${ArtifactStoreBucket}
- !Sub arn:aws:s3:::${ArtifactStoreBucket}/*
- Sid: FullAccess
Effect: Allow
Action:
- cloudformation:*
- iam:PassRole
- codecommit:GetRepository
- codecommit:ListBranches
- codecommit:GetUploadArchiveStatus
- codecommit:UploadArchive
- codecommit:CancelUploadArchive
- codecommit:GetBranch
- codecommit:GetCommit
Resource: "*"
- Sid: CodeBuildAccess
Effect: Allow
Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
Resource: !GetAtt CodeBuildProjectLint.Arn
- Sid: CodeBuildChangesetAccess
Effect: Allow
Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
Resource: !GetAtt CodeBuildProjectChangeset.Arn
- Sid: SNSAccess
Effect: Allow
Action:
- sns:Publish
Resource: !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ResourceName}-topic
# ------------------------------------------------------------#
# CodePipeline
# ------------------------------------------------------------#
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub ${ResourceName}-pipeline
RoleArn: !GetAtt PipelineRole.Arn
ArtifactStore:
Type: S3
Location: !Ref ArtifactStoreBucket
Stages:
- Name: Source
Actions:
- Name: download-source
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
Configuration:
RepositoryName: !Ref REPOSITORYNAME
BranchName: main
PollForSourceChanges: true #ポーリングベースのパイプラインでは、"true"に設定
OutputArtifacts:
- Name: SourceOutput
- Name: Test
Actions:
- InputArtifacts:
- Name: SourceOutput
Name: testing
ActionTypeId:
Category: Test
Owner: AWS
Version: 1
Provider: CodeBuild
Configuration:
ProjectName: !Ref CodeBuildProjectLint
- Name: Build
Actions:
- InputArtifacts:
- Name: SourceOutput
Name: changeset
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
OutputArtifacts:
- Name: BuildOutput
Configuration:
ProjectName: !Ref CodeBuildProjectChangeset
Namespace: BuildVariables
- Name: Approval
Actions:
- Name: approve-changeset
ActionTypeId:
Category: Approval
Owner: AWS
Version: 1
Provider: Manual
Configuration:
ExternalEntityLink: !Sub https://${AWS::Region}.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/changesets/changes?stackId=#{BuildVariables.SackId}&changeSetId=#{BuildVariables.ChangeSetId}
NotificationArn: !GetAtt SNSTopic.TopicArn
- Name: Deploy
Actions:
- Name: execute-changeset
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
Configuration:
StackName: !Join [ '-', [ !Ref ResourceName, 'infra-stack' ] ]
ActionMode: CHANGE_SET_EXECUTE
ChangeSetName: changeset
RoleArn: !GetAtt CloudformationRole.Arn
# ------------------------------------------------------------#
# SNS
# ------------------------------------------------------------#
SNSTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: !Ref MailAddress
Protocol: email
TopicName: !Sub ${ResourceName}-topic
ポーリングベースのパイプラインの一覧の取得
今回はboto3(Python)を使用して、ポーリングベースのパイプラインの一覧を取得してみます。
Cloud9へのboto3のインストール
以下のコマンドを実行して、boto3ライブラリのインストールをします。
pip install boto3
以下のコマンドを実行して、バージョンが返却されればインストール済みとなります。今回は、”boto3 1.33.11″が返ってきています。
pip list | grep boto3
Pythonスクリプトの作成
Cloud9におけるGUI経由でのファイル作成方法は、以下を参照ください。
以下のPythonファイルを任意のディレクトリに作成してください。ファイル名は、”PollingPipelinesExtractor.py”とします。
import boto3
import sys
import time
import math
hasNextToken = True
nextToken = ""
pollablePipelines = []
lastExecutedTimes = []
if len(sys.argv) == 1:
raise Exception("Please provide region name.")
session = boto3.Session(profile_name='default', region_name=sys.argv[1])
codepipeline = session.client('codepipeline')
def is_pollable_action(action):
actionTypeId = action['actionTypeId']
configuration = action['configuration']
return actionTypeId['owner'] in {"AWS", "ThirdParty"} and actionTypeId['provider'] in {"GitHub", "CodeCommit", "S3"} and ('PollForSourceChanges' not in configuration or configuration['PollForSourceChanges'] == 'true')
def has_pollable_actions(pipeline):
hasPollableAction = False
pipelineDefinition = codepipeline.get_pipeline(name=pipeline['name'])['pipeline']
for action in pipelineDefinition['stages'][0]['actions']:
hasPollableAction = is_pollable_action(action)
if hasPollableAction:
break
return hasPollableAction
def get_last_executed_time(pipelineName):
pipelineExecutions=codepipeline.list_pipeline_executions(pipelineName=pipelineName)['pipelineExecutionSummaries']
if pipelineExecutions:
return pipelineExecutions[0]['startTime'].strftime("%A %m/%d/%Y, %H:%M:%S")
else:
return "Not executed in last year"
while hasNextToken:
if nextToken=="":
list_pipelines_response = codepipeline.list_pipelines()
else:
list_pipelines_response = codepipeline.list_pipelines(nextToken=nextToken)
if 'nextToken' in list_pipelines_response:
nextToken = list_pipelines_response['nextToken']
else:
hasNextToken= False
for pipeline in list_pipelines_response['pipelines']:
if has_pollable_actions(pipeline):
pollablePipelines.append(pipeline['name'])
lastExecutedTimes.append(get_last_executed_time(pipeline['name']))
fileName="{region}-{timeNow}.csv".format(region=sys.argv[1],timeNow=math.trunc(time.time()))
file = open(fileName, 'w')
print ("{:<30} {:<30} {:<30}".format('Polling Pipeline Name', '|','Last Executed Time'))
print ("{:<30} {:<30} {:<30}".format('_____________________', '|','__________________'))
for i in range(len(pollablePipelines)):
print("{:<30} {:<30} {:<30}".format(pollablePipelines[i], '|', lastExecutedTimes[i]))
file.write("{pipeline},".format(pipeline=pollablePipelines[i]))
file.close()
print("\nSaving Polling Pipeline Names to file {fileName}".format(fileName=fileName))
Pythonスクリプトの実行
以下のコマンドを実行して、pythonスクリプトを実行します。
引数として、指定のリージョンを入力します。ここでは、東京リージョンの”ap-northeast-1″を指定します。
python3 PollingPipelinesExtractor.py ap-northeast-1
指定のリージョン内に存在しているポーリングベースのパイプラインの一覧を取得することができます。これで、どのパイプラインがポーリングベースを採用しているのか一目瞭然ですね。またCSVファイルとしても出力されています。
今回は、”cicd-20231210-pipeline”を新規作成したので表示されています。ご自身で作成したものと読み替えてください。
イベントベースのパイプラインへ移行
ポーリングベースからイベントベースへ移行するために、CloudFormationテンプレートの修正をしていきます。
PollForSourceChangesの変更
以下のように、ポーリングベースを採用しないようにCodePipelineの”PollForSourceChanges”プロパティを”false”に変更します。
Stages:
- Name: Source
Actions:
- Name: download-source
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
Configuration:
RepositoryName: !Ref REPOSITORYNAME
BranchName: main
PollForSourceChanges: false #イベントベースを採用するためfalseに変更
OutputArtifacts:
- Name: SourceOutput
EventBridgeが利用するIAMポリシー・ロールの追加
以下のように、EventBridgeが利用するためのIAMポリシー・ロールを作成するための記述を追加します。
EventBridgeがCodePipelineを起動できる権限を付与しています。
# ------------------------------------------------------------#
# CodePipeline Events Role (IAM)
# ------------------------------------------------------------#
PipelineEventsRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: events.amazonaws.com
Path: /
ManagedPolicyArns:
- !Ref PipelineEventsPolicy
RoleName: !Sub "IRL-EVENTBRIDGE-CodePipelineAccess"
# ------------------------------------------------------------#
# CodePipeline Events Role Policy (IAM)
# ------------------------------------------------------------#
PipelineEventsPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: CodePipelineAccessForEvents
PolicyDocument:
Statement:
- Action: codepipeline:StartPipelineExecution
Effect: Allow
Resource:
- !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}
Version: "2012-10-17"
EventBridgeの追加
以下のように、EventBridge本体の記述を追加します。対象のリポジトリや付与するロール等の指定もしています。
これによりCodeCommitのブランチの更新をトリガーにCodePipelineを起動できるようになります。
# ------------------------------------------------------------#
# EventBridge Rule for Starting CodePipeline
# ------------------------------------------------------------#
PipelineEventsRule:
Type: AWS::Events::Rule
Properties:
Name: !Sub ${ResourceName}-rule-pipeline
EventBusName: !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:event-bus/default"
EventPattern:
source:
- aws.codecommit
resources:
- !Sub arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${REPOSITORYNAME}
detail-type:
- "CodeCommit Repository State Change"
detail:
event:
- referenceCreated
- referenceUpdated
referenceName:
- main
State: ENABLED
Targets:
- Arn:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codepipeline:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- ":"
- Ref: Pipeline
Id: Target
RoleArn: !GetAtt PipelineEventsRole.Arn
完成したテンプレート
完成したテンプレートは、以下の通りです。
AWSTemplateFormatVersion: 2010-09-09
Description: cfn CI/CD Pipeline
Parameters:
ResourceName:
Type: String
REPOSITORYNAME:
Type: String
Description: aws codecommit repository name
STACKNAME:
Type: String
MailAddress:
Type: String
Resources:
ArtifactStoreBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub s3bucket-${AWS::AccountId}-artifactbucket
CodeBuildBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub s3bucket-${AWS::AccountId}-codebuildtbucket
# ------------------------------------------------------------#
# EventBridge Rule for Starting CodePipeline
# ------------------------------------------------------------#
PipelineEventsRule:
Type: AWS::Events::Rule
Properties:
Name: !Sub ${ResourceName}-rule-pipeline
EventBusName: !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:event-bus/default"
EventPattern:
source:
- aws.codecommit
resources:
- !Sub arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${REPOSITORYNAME}
detail-type:
- "CodeCommit Repository State Change"
detail:
event:
- referenceCreated
- referenceUpdated
referenceName:
- main
State: ENABLED
Targets:
- Arn:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codepipeline:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- ":"
- Ref: Pipeline
Id: Target
RoleArn: !GetAtt PipelineEventsRole.Arn
# ------------------------------------------------------------#
# CodePipeline Events Role (IAM)
# ------------------------------------------------------------#
PipelineEventsRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: events.amazonaws.com
Path: /
ManagedPolicyArns:
- !Ref PipelineEventsPolicy
RoleName: !Sub "IRL-EVENTBRIDGE-CodePipelineAccess"
# ------------------------------------------------------------#
# CodePipeline Events Role Policy (IAM)
# ------------------------------------------------------------#
PipelineEventsPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: CodePipelineAccessForEvents
PolicyDocument:
Statement:
- Action: codepipeline:StartPipelineExecution
Effect: Allow
Resource:
- !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodeBuild Role (IAM)
# ------------------------------------------------------------#
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Path: /
ManagedPolicyArns:
- !Ref CodeBuildPolicy
- arn:aws:iam::aws:policy/AWSCloudFormationFullAccess
RoleName: !Sub "IRL-CODEBUILD-S3CloudWatchlogsAccess"
# ------------------------------------------------------------#
# CodeBuild Role Policy (IAM)
# ------------------------------------------------------------#
CodeBuildPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: CodeBuildAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: CloudWatchLogsAccess
Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*
- Sid: S3Access
Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:GetObjectVersion
Resource:
- !Sub arn:aws:s3:::${ArtifactStoreBucket}
- !Sub arn:aws:s3:::${ArtifactStoreBucket}/*
- !Sub arn:aws:s3:::${CodeBuildBucket}
- !Sub arn:aws:s3:::${CodeBuildBucket}/*
- Sid: IAMPass
Effect: Allow
Action:
- iam:PassRole
Resource: "*"
- Sid: CloudFormationAccess
Effect: Allow
Action: cloudformation:ValidateTemplate
Resource: "*"
# ------------------------------------------------------------#
# CodeBuild linter Project
# ------------------------------------------------------------#
CodeBuildProjectLint:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${ResourceName}-project-lint
ServiceRole: !GetAtt CodeBuildRole.Arn
Artifacts:
Type: CODEPIPELINE
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
EnvironmentVariables:
- Name: AWS_REGION
Value: !Ref AWS::Region
- Name: S3_BUCKET
Value: !Ref CodeBuildBucket
Source:
Type: CODEPIPELINE
# ------------------------------------------------------------#
# CodeBuild changeset Project
# ------------------------------------------------------------#
CodeBuildProjectChangeset:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${ResourceName}-project-changeset
ServiceRole: !GetAtt CodeBuildRole.Arn
Artifacts:
Type: CODEPIPELINE
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
EnvironmentVariables:
- Name: AWS_REGION
Value: !Ref AWS::Region
- Name: S3_BUCKET
Value: !Ref CodeBuildBucket
- Name: STACK_NAME
Value: !Ref STACKNAME
- Name: CFNROLE_ARN
Value: !GetAtt CloudformationRole.Arn
Source:
Type: CODEPIPELINE
BuildSpec: changeset-buildspec.yaml
# ------------------------------------------------------------#
# CloudFormation Role (IAM)
# ------------------------------------------------------------#
CloudformationRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service: cloudformation.amazonaws.com
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
RoleName: "IRL-CLOUDFORMATION-ServiceFullAccess"
# ------------------------------------------------------------#
# CodePipeline Role (IAM)
# ------------------------------------------------------------#
PipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Path: /
ManagedPolicyArns:
- !Ref PipelinePolicy
RoleName: "IRL-CODEPIPELINE-Access"
# ------------------------------------------------------------#
# CodePipeline Role Policy (IAM)
# ------------------------------------------------------------#
PipelinePolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: CodePipelineAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: S3FullAccess
Effect: Allow
Action: s3:*
Resource:
- !Sub arn:aws:s3:::${ArtifactStoreBucket}
- !Sub arn:aws:s3:::${ArtifactStoreBucket}/*
- Sid: FullAccess
Effect: Allow
Action:
- cloudformation:*
- iam:PassRole
- codecommit:GetRepository
- codecommit:ListBranches
- codecommit:GetUploadArchiveStatus
- codecommit:UploadArchive
- codecommit:CancelUploadArchive
- codecommit:GetBranch
- codecommit:GetCommit
Resource: "*"
- Sid: CodeBuildAccess
Effect: Allow
Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
Resource: !GetAtt CodeBuildProjectLint.Arn
- Sid: CodeBuildChangesetAccess
Effect: Allow
Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
Resource: !GetAtt CodeBuildProjectChangeset.Arn
- Sid: SNSAccess
Effect: Allow
Action:
- sns:Publish
Resource: !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ResourceName}-topic
# ------------------------------------------------------------#
# CodePipeline
# ------------------------------------------------------------#
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub ${ResourceName}-pipeline
RoleArn: !GetAtt PipelineRole.Arn
ArtifactStore:
Type: S3
Location: !Ref ArtifactStoreBucket
Stages:
- Name: Source
Actions:
- Name: download-source
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
Configuration:
RepositoryName: !Ref REPOSITORYNAME
BranchName: main
PollForSourceChanges: false #イベントベースを採用するためfalseに変更
OutputArtifacts:
- Name: SourceOutput
- Name: Test
Actions:
- InputArtifacts:
- Name: SourceOutput
Name: testing
ActionTypeId:
Category: Test
Owner: AWS
Version: 1
Provider: CodeBuild
Configuration:
ProjectName: !Ref CodeBuildProjectLint
- Name: Build
Actions:
- InputArtifacts:
- Name: SourceOutput
Name: changeset
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
OutputArtifacts:
- Name: BuildOutput
Configuration:
ProjectName: !Ref CodeBuildProjectChangeset
Namespace: BuildVariables
- Name: Approval
Actions:
- Name: approve-changeset
ActionTypeId:
Category: Approval
Owner: AWS
Version: 1
Provider: Manual
Configuration:
ExternalEntityLink: !Sub https://${AWS::Region}.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/changesets/changes?stackId=#{BuildVariables.SackId}&changeSetId=#{BuildVariables.ChangeSetId}
NotificationArn: !GetAtt SNSTopic.TopicArn
- Name: Deploy
Actions:
- Name: execute-changeset
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
Configuration:
StackName: !Join [ '-', [ !Ref ResourceName, 'infra-stack' ] ]
ActionMode: CHANGE_SET_EXECUTE
ChangeSetName: changeset
RoleArn: !GetAtt CloudformationRole.Arn
# ------------------------------------------------------------#
# SNS
# ------------------------------------------------------------#
SNSTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Endpoint: !Ref MailAddress
Protocol: email
TopicName: !Sub ${ResourceName}-topic
CI/CDパイプラインの更新
上記テンプレートを使用して、CI/CDパイプラインのスタックを更新します。
CloudFormationコンソールから該当のスタック選択して、”更新”を押下してください。
修正済みのテンプレートファイルをアップデートして、”次へ”を押下してください。
既存のパラメータ等は変更することなく、”次へ”を押下してください。
“次へ”を押下してください。
最後にレビュー画面に遷移します。内容に間違いがないか確認します。
変更セットのレビューにて、IAMポリシー・IAMロール・EventBridgeルールが追加されることを確認します。またCodePipelineでは、変更があることも確認します。問題なければ”送信”を押下してください。
数分経過すると、スタックの更新が完了します。
移行の確認
移行が完了したかどうか、こちらの手順で再度スクリプトを実行することで確かめます。
先ほどまで存在した”cicd-20231210-pipeline”が表示されていないため、イベントベースのパイプラインとして正常に認識されています。
これにて移行完了となります。お疲れ様でした。
パイプライン起動確認
念の為、イベントベースのパイプラインが起動するか確認しておきます。
CodeCommitにプッシュすると、パイプラインが起動していることが分かります。(承認ステージを組み込んでいるため、レビュー中で一時停止しています。)
また、イベントベースへの移行を勧める警告メッセージも表示されなくなっています。
ちなみに、ポーリングベースのパイプラインを利用していると、CodePipelineの対象パイプラインの画面を開くたびに以下のように警告メッセージが表示されます。
パイプラインがアクティブの場合:
このパイプラインには、ポーリング用に設定されたソース(download-source)があります。変更検出用に推奨されるイベントベースのメカニズムにパイプラインを移行(更新)します。詳細については、「移行ガイド」を参照してください。
30日以上パイプラインを起動していない(アクティブでない)場合:
○か月前時点で、CodePipelineはこのパイプラインのポーリングを無効にしています。これは、以前30日間に実行されていないためです。推奨されるイベントベースのメカニズムを使用して、新しいパイプライン実行を開始します。
最後に
いかがでしたでしょうか。
CodeCommitをソースとしたCloudFormationで構築済みのポーリングベースのCodePipelineをイベントベースへと移行しました。
既存のCodePipelineでポーリングベースを利用している方は、是非この手順に沿って移行の検討をしていただければと思います。また新規でパイプラインを構築する際は、イベントベースでパイプラインを構築するように意識してください。
本記事が皆様のお役にたてば幸いです。
ではサウナラ~?













