From 45c77bab2b928ce83bd31d36130b70ff5feacfdf Mon Sep 17 00:00:00 2001 From: Daisuke Date: Sun, 4 Jan 2026 12:44:31 +0900 Subject: [PATCH] feat: add CodePipeline for Lambda deployment automation - Add CodeBuild project for building and pushing Docker images - Add CodePipeline with S3 source and build stages - Add EventBridge rule to trigger pipeline on S3 object creation - Configure IAM roles and policies for pipeline execution --- infra/cfn/blog-lambda-pipeline.yaml | 233 ++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 infra/cfn/blog-lambda-pipeline.yaml diff --git a/infra/cfn/blog-lambda-pipeline.yaml b/infra/cfn/blog-lambda-pipeline.yaml new file mode 100644 index 0000000..f06d212 --- /dev/null +++ b/infra/cfn/blog-lambda-pipeline.yaml @@ -0,0 +1,233 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: S3 -> CodePipeline -> CodeBuild(ARM) -> ECR pipeline for Blog Lambda + +Parameters: + SourceBucketName: + Type: String + Default: blog-lambda-source-bucket + Description: S3 bucket name for source code + + SourceObjectKey: + Type: String + Default: blog-lambda-source.zip + Description: S3 object key for source code archive + +Resources: + + SourceBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub "${AWS::Region}-${AWS::AccountId}-${SourceBucketName}" + Tags: + - Key: Project + Value: Blog-Deployment + VersioningConfiguration: + Status: Enabled + NotificationConfiguration: + EventBridgeConfiguration: + EventBridgeEnabled: true + + CodeBuildRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: codebuild.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: CodeBuildPolicy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Resource: "*" + - Effect: Allow + Action: + - ecr:GetAuthorizationToken + Resource: "*" + - Effect: Allow + Action: + - ecr:BatchCheckLayerAvailability + - ecr:InitiateLayerUpload + - ecr:UploadLayerPart + - ecr:CompleteLayerUpload + - ecr:PutImage + Resource: + Fn::ImportValue: BlogDeployment-RepositoryArn + - Effect: Allow + Action: + - s3:GetObject + - s3:PutObject + - s3:ListBucket + Resource: + - !Sub "arn:aws:s3:::codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket" + - !Sub "arn:aws:s3:::codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket/*" + - !GetAtt SourceBucket.Arn + - !Sub "${SourceBucket.Arn}/*" + + BlogLambdaBuildProject: + Type: AWS::CodeBuild::Project + Properties: + Name: blog-lambda-build + ServiceRole: !GetAtt CodeBuildRole.Arn + Artifacts: + Type: CODEPIPELINE + Environment: + Type: ARM_CONTAINER + ComputeType: BUILD_GENERAL1_SMALL + Image: aws/codebuild/amazonlinux2-aarch64-standard:3.0 + PrivilegedMode: true + EnvironmentVariables: + - Name: ECR_REPOSITORY_URI + Value: + Fn::ImportValue: BlogDeployment-RepositoryUri + - Name: AWS_DEFAULT_REGION + Value: !Ref AWS::Region + - Name: AWS_ACCOUNT_ID + Value: !Ref AWS::AccountId + Source: + Type: CODEPIPELINE + BuildSpec: ci/buildspec.yml + TimeoutInMinutes: 30 + + CodePipelineRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: codepipeline.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: CodePipelinePolicy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - s3:GetBucketAcl + - s3:GetObjectTagging + - s3:GetObjectVersionTagging + - s3:GetObject + - s3:GetObjectVersion + - s3:PutObject + - s3:ListBucket + - s3:GetBucketLocation + - s3:GetBucketVersioning + Resource: + - !Sub "arn:aws:s3:::codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket" + - !Sub "arn:aws:s3:::codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket/*" + - !GetAtt SourceBucket.Arn + - !Sub "${SourceBucket.Arn}/*" + - Effect: Allow + Action: + - codebuild:StartBuild + - codebuild:BatchGetBuilds + Resource: + - !Sub "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:build/*" + - !Sub "arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/*" + - Effect: Allow + Action: + - codepipeline:PutApprovalResult + - codepipeline:StartPipelineExecution + Resource: !Sub "arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:*" + + BlogLambdaPipeline: + Type: AWS::CodePipeline::Pipeline + Properties: + Name: blog-lambda-pipeline + PipelineType: V2 + RoleArn: !GetAtt CodePipelineRole.Arn + ArtifactStore: + Type: S3 + Location: !Sub "codebuild-${AWS::Region}-${AWS::AccountId}-input-bucket" + Stages: + - Name: Source + Actions: + - Name: S3Source + ActionTypeId: + Category: Source + Owner: AWS + Provider: S3 + Version: "1" + Configuration: + S3Bucket: !Ref SourceBucket + S3ObjectKey: !Ref SourceObjectKey + PollForSourceChanges: false + OutputArtifacts: + - Name: SourceOutput + - Name: Build + Actions: + - Name: BuildAndPushImage + ActionTypeId: + Category: Build + Owner: AWS + Provider: CodeBuild + Version: "1" + InputArtifacts: + - Name: SourceOutput + Configuration: + ProjectName: !Ref BlogLambdaBuildProject + + S3SourceChangeRule: + Type: AWS::Events::Rule + Properties: + Description: Trigger CodePipeline on S3 source update + EventPattern: + source: + - aws.s3 + detail-type: + - Object Created + detail: + bucket: + name: + - !Ref SourceBucket + object: + key: + - !Ref SourceObjectKey + Targets: + - Arn: !Sub "arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${BlogLambdaPipeline}" + RoleArn: !GetAtt EventBridgeInvokePipelineRole.Arn + Id: CodePipelineTarget + + EventBridgeInvokePipelineRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: events.amazonaws.com + Action: sts:AssumeRole + Policies: + - PolicyName: AllowStartPipeline + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - codepipeline:StartPipelineExecution + Resource: !Sub "arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${BlogLambdaPipeline}" + +Outputs: + SourceBucketName: + Description: S3 bucket for source code + Value: !Ref SourceBucket + Export: + Name: !Sub "${AWS::StackName}-SourceBucket" + + PipelineName: + Description: CodePipeline name + Value: !Ref BlogLambdaPipeline + Export: + Name: !Sub "${AWS::StackName}-PipelineName"