Restructure project layout and add ECR repository CloudFormation template
- Move application entrypoint to cmd/lambda/ - Move Dockerfile to docker/ for clearer build context separation - Promote go.mod/go.sum to project root - Move CloudFormation templates under infra/cfn/ for consistent infra layout - Add new template-container-repository.yaml defining ECR repository (blog-deployment) - Move Lambda test files to test/ directory
This commit is contained in:
parent
aa1f4a91bf
commit
0b67765510
11 changed files with 21 additions and 0 deletions
19
infra/cfn/template-blog-source-bucket.yaml
Normal file
19
infra/cfn/template-blog-source-bucket.yaml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
|
||||
Parameters:
|
||||
BucketName:
|
||||
Type: String
|
||||
Description: "The name for the S3 bucket to be used for public website hosting (must be globally unique)"
|
||||
Default: "naputo-blog-source"
|
||||
|
||||
Resources:
|
||||
|
||||
SourceBucket:
|
||||
Type: AWS::S3::Bucket
|
||||
Properties:
|
||||
BucketName: !Ref BucketName
|
||||
Tags:
|
||||
- Key: Project
|
||||
Value: Git-server
|
||||
VersioningConfiguration:
|
||||
Status: Enabled
|
||||
79
infra/cfn/template-cloudfront.yaml
Normal file
79
infra/cfn/template-cloudfront.yaml
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
|
||||
Parameters:
|
||||
WebsiteBucketName:
|
||||
Type: String
|
||||
Description: "The name for the S3 bucket to be used for public website hosting (must be globally unique)"
|
||||
Default: "naputo-blog-public"
|
||||
|
||||
Resources:
|
||||
|
||||
AddIndexFunction:
|
||||
Type: AWS::CloudFront::Function
|
||||
Properties:
|
||||
Name: "AddIndexFunction"
|
||||
AutoPublish: true
|
||||
FunctionConfig:
|
||||
Comment: "Appends index.html for directory URIs"
|
||||
Runtime: cloudfront-js-1.0
|
||||
FunctionCode: |
|
||||
function handler(event) {
|
||||
var request = event.request;
|
||||
var uri = request.uri;
|
||||
if (uri.endsWith("/")) {
|
||||
request.uri += "index.html";
|
||||
} else if (uri === "") {
|
||||
request.uri = "/index.html";
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
BlogOriginAccessControl:
|
||||
Type: AWS::CloudFront::OriginAccessControl
|
||||
Properties:
|
||||
OriginAccessControlConfig:
|
||||
Name: "MyBlogOAC"
|
||||
OriginAccessControlOriginType: s3
|
||||
SigningBehavior: always
|
||||
SigningProtocol: sigv4
|
||||
|
||||
BlogCloudFrontDistribution:
|
||||
Type: AWS::CloudFront::Distribution
|
||||
Properties:
|
||||
DistributionConfig:
|
||||
Enabled: true
|
||||
DefaultRootObject: index.html
|
||||
Origins:
|
||||
- Id: S3WebsiteOrigin
|
||||
DomainName: !Sub "${WebsiteBucketName}.s3.amazonaws.com"
|
||||
OriginAccessControlId: !Ref BlogOriginAccessControl
|
||||
S3OriginConfig: {}
|
||||
DefaultCacheBehavior:
|
||||
TargetOriginId: S3WebsiteOrigin
|
||||
ViewerProtocolPolicy: redirect-to-https
|
||||
AllowedMethods:
|
||||
- GET
|
||||
- HEAD
|
||||
CachedMethods:
|
||||
- GET
|
||||
- HEAD
|
||||
ForwardedValues:
|
||||
QueryString: false
|
||||
Cookies:
|
||||
Forward: none
|
||||
FunctionAssociations:
|
||||
- EventType: viewer-request
|
||||
FunctionARN: !GetAtt AddIndexFunction.FunctionARN
|
||||
Aliases:
|
||||
- blog.n-daisuke897.com
|
||||
ViewerCertificate:
|
||||
AcmCertificateArn: !Sub "arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/4d3e8182-71e0-4ccb-a437-36523f61a6c0"
|
||||
SslSupportMethod: sni-only
|
||||
MinimumProtocolVersion: TLSv1.2_2021
|
||||
PriceClass: PriceClass_200
|
||||
|
||||
Outputs:
|
||||
IdBlogCloudFrontDistribution:
|
||||
Value: !Ref BlogCloudFrontDistribution
|
||||
Export:
|
||||
Name: BlogCloudFrontDistribution-ID
|
||||
216
infra/cfn/template-codepipeline.yaml
Normal file
216
infra/cfn/template-codepipeline.yaml
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
|
||||
Parameters:
|
||||
BucketName:
|
||||
Type: String
|
||||
Description: "The name for the S3 bucket to be used for public website hosting (must be globally unique)"
|
||||
Default: "naputo-blog-public"
|
||||
|
||||
Resources:
|
||||
|
||||
WebsiteBucket:
|
||||
Type: AWS::S3::Bucket
|
||||
Properties:
|
||||
BucketName: !Ref BucketName
|
||||
PublicAccessBlockConfiguration:
|
||||
BlockPublicAcls: true
|
||||
BlockPublicPolicy: true
|
||||
IgnorePublicAcls: true
|
||||
RestrictPublicBuckets: true
|
||||
|
||||
WebsiteBucketPolicy:
|
||||
Type: AWS::S3::BucketPolicy
|
||||
Properties:
|
||||
Bucket: !Ref WebsiteBucket
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Sid: AllowCodePipelineUpdates
|
||||
Effect: Allow
|
||||
Principal:
|
||||
AWS: !GetAtt CodePipelineRole.Arn
|
||||
Action:
|
||||
- s3:PutObject
|
||||
- s3:DeleteObject
|
||||
Resource: !Sub "arn:aws:s3:::${WebsiteBucket}/*"
|
||||
- Sid: AllowCloudFrontOACGetObject
|
||||
Effect: Allow
|
||||
Principal:
|
||||
Service: cloudfront.amazonaws.com
|
||||
Action:
|
||||
- s3:GetObject
|
||||
Resource: !Sub "arn:aws:s3:::${WebsiteBucket}/*"
|
||||
Condition:
|
||||
StringEquals:
|
||||
AWS:SourceArn:
|
||||
Fn::Sub:
|
||||
- arn:aws:cloudfront::${AWS::AccountId}:distribution/${MyCloudFrontDistribution}
|
||||
- MyCloudFrontDistribution:
|
||||
Fn::ImportValue: BlogCloudFrontDistribution-ID
|
||||
|
||||
CodeBuildServiceRole:
|
||||
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:
|
||||
- s3:GetObject
|
||||
- s3:PutObject
|
||||
- s3:ListBucket
|
||||
Resource:
|
||||
- "arn:aws:s3:::codebuild-ap-northeast-1-692859919890-input-bucket"
|
||||
- "arn:aws:s3:::codebuild-ap-northeast-1-692859919890-input-bucket/*"
|
||||
- "arn:aws:s3:::naputo-blog-source"
|
||||
- "arn:aws:s3:::naputo-blog-source/*"
|
||||
|
||||
MyBlogCodeBuildProject:
|
||||
Type: AWS::CodeBuild::Project
|
||||
Properties:
|
||||
ServiceRole: !GetAtt CodeBuildServiceRole.Arn
|
||||
Artifacts:
|
||||
Type: CODEPIPELINE
|
||||
Environment:
|
||||
ComputeType: BUILD_LAMBDA_1GB
|
||||
Image: aws/codebuild/amazonlinux-x86_64-lambda-standard:nodejs22
|
||||
Type: LINUX_LAMBDA_CONTAINER
|
||||
Source:
|
||||
Type: CODEPIPELINE
|
||||
|
||||
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:
|
||||
# Permissions for accessing the artifacts bucket
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- s3:GetObject
|
||||
- s3:GetObjectVersion
|
||||
- s3:PutObject
|
||||
- s3:ListBucket
|
||||
- s3:GetBucketLocation
|
||||
- s3:GetBucketVersioning
|
||||
Resource:
|
||||
- "arn:aws:s3:::codebuild-ap-northeast-1-692859919890-input-bucket"
|
||||
- "arn:aws:s3:::codebuild-ap-northeast-1-692859919890-input-bucket/*"
|
||||
- "arn:aws:s3:::naputo-blog-source"
|
||||
- "arn:aws:s3:::naputo-blog-source/*"
|
||||
# Permissions for CloudFormation actions
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- cloudformation:CreateStack
|
||||
- cloudformation:DeleteStack
|
||||
- cloudformation:UpdateStack
|
||||
- cloudformation:DescribeStacks
|
||||
- cloudformation:DescribeStackEvents
|
||||
- cloudformation:ValidateTemplate
|
||||
Resource: "*"
|
||||
# Permissions for CodeBuild (if used)
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- codebuild:StartBuild
|
||||
- codebuild:BatchGetBuilds
|
||||
Resource: "*"
|
||||
# Permissions for manual approval actions in CodePipeline
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- codepipeline:PutApprovalResult
|
||||
Resource: "*"
|
||||
|
||||
MyBlogPipeline:
|
||||
Type: AWS::CodePipeline::Pipeline
|
||||
Properties:
|
||||
PipelineType: V2
|
||||
ArtifactStore:
|
||||
Type: S3
|
||||
Location: "codebuild-ap-northeast-1-692859919890-input-bucket"
|
||||
RoleArn: !GetAtt CodePipelineRole.Arn
|
||||
Tags:
|
||||
- Key: Project
|
||||
Value: Git-server
|
||||
Stages:
|
||||
- Name: Source
|
||||
Actions:
|
||||
- Name: S3Source
|
||||
ActionTypeId:
|
||||
Category: Source
|
||||
Owner: AWS
|
||||
Provider: S3
|
||||
Version: "1"
|
||||
OutputArtifacts:
|
||||
- Name: SourceArtifact
|
||||
Configuration:
|
||||
S3Bucket: naputo-blog-source
|
||||
S3ObjectKey: source.zip
|
||||
RunOrder: 1
|
||||
- Name: Build
|
||||
Actions:
|
||||
- Name: CodeBuild
|
||||
ActionTypeId:
|
||||
Category: Build
|
||||
Owner: AWS
|
||||
Provider: CodeBuild
|
||||
Version: "1"
|
||||
Configuration:
|
||||
ProjectName: !Ref MyBlogCodeBuildProject
|
||||
OutputArtifacts:
|
||||
- Name: BuildArtifact
|
||||
InputArtifacts:
|
||||
- Name: SourceArtifact
|
||||
RunOrder: 1
|
||||
- Name: Approval
|
||||
Actions:
|
||||
- Name: ManualApproval
|
||||
ActionTypeId:
|
||||
Category: Approval
|
||||
Owner: AWS
|
||||
Provider: Manual
|
||||
Version: "1"
|
||||
RunOrder: 1
|
||||
Configuration:
|
||||
CustomData: "Please review the build artifact and approve the deployment."
|
||||
- Name: Deploy
|
||||
Actions:
|
||||
- Name: S3Deploy
|
||||
ActionTypeId:
|
||||
Category: Deploy
|
||||
Owner: AWS
|
||||
Provider: S3
|
||||
Version: "1"
|
||||
InputArtifacts:
|
||||
- Name: BuildArtifact
|
||||
Configuration:
|
||||
BucketName: !Ref WebsiteBucket
|
||||
Extract: 'true'
|
||||
RunOrder: 1
|
||||
21
infra/cfn/template-container-repository.yaml
Normal file
21
infra/cfn/template-container-repository.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
AWSTemplateFormatVersion: "2010-09-09"
|
||||
|
||||
Parameters:
|
||||
RepositoryName:
|
||||
Type: String
|
||||
Default: blog-deployment
|
||||
|
||||
Resources:
|
||||
# ECR Repository
|
||||
Repository:
|
||||
Type: AWS::ECR::Repository
|
||||
DeletionPolicy: Retain
|
||||
Properties:
|
||||
RepositoryName: !Ref RepositoryName
|
||||
ImageScanningConfiguration:
|
||||
ScanOnPush: true
|
||||
|
||||
Outputs:
|
||||
RepositoryUri:
|
||||
Description: URI of the ECR repository
|
||||
Value: !GetAtt Repository.RepositoryUri
|
||||
88
infra/cfn/template-lambda-function.yaml
Normal file
88
infra/cfn/template-lambda-function.yaml
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: AWS::Serverless-2016-10-31
|
||||
Parameters:
|
||||
StageName:
|
||||
Type: String
|
||||
Default: Prod
|
||||
Description: Name of the API stage.
|
||||
|
||||
Resources:
|
||||
|
||||
MyLambdaRole:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service:
|
||||
- lambda.amazonaws.com
|
||||
Action: sts:AssumeRole
|
||||
Policies:
|
||||
- PolicyName: LambdaS3PutObjectPolicy
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- s3:PutObject
|
||||
Resource: arn:aws:s3:::naputo-blog-source/*
|
||||
ManagedPolicyArns:
|
||||
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
|
||||
|
||||
MyLambdaFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
PackageType: Image
|
||||
ImageUri: 692859919890.dkr.ecr.ap-northeast-1.amazonaws.com/blog-deployment:latest
|
||||
Timeout: 30
|
||||
MemorySize: 256
|
||||
Environment:
|
||||
Variables:
|
||||
REPO_URL: "https://git.n-daisuke897.com/nakada0907/n-daisuke897-blog.git"
|
||||
REPO_BRANCH: "main"
|
||||
S3_BUCKET: "naputo-blog-source"
|
||||
S3_KEY: "source.zip"
|
||||
WEBHOOK_SECRET:
|
||||
Fn::Sub:
|
||||
- "{{resolve:secretsmanager:${SecretArn}:SecretString:secretNumber:AWSCURRENT}}"
|
||||
- SecretArn:
|
||||
Fn::ImportValue: SecretForWebhook-ARN
|
||||
Role: !GetAtt MyLambdaRole.Arn
|
||||
Events:
|
||||
ForgejoWebhook:
|
||||
Type: Api
|
||||
Properties:
|
||||
RestApiId: !Ref MyApi
|
||||
Path: /forgejo-webhook
|
||||
Method: POST
|
||||
|
||||
MyApi:
|
||||
Type: AWS::Serverless::Api
|
||||
Properties:
|
||||
StageName: !Ref StageName
|
||||
EndpointConfiguration: REGIONAL
|
||||
DefinitionBody:
|
||||
openapi: "3.0.1"
|
||||
info:
|
||||
title: "Forgejo Webhook API"
|
||||
version: "1.0"
|
||||
paths:
|
||||
/forgejo-webhook:
|
||||
post:
|
||||
summary: "Trigger Lambda via Forgejo Webhook"
|
||||
x-amazon-apigateway-integration:
|
||||
uri:
|
||||
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyLambdaFunction.Arn}/invocations
|
||||
httpMethod: POST
|
||||
type: aws_proxy
|
||||
responses:
|
||||
'200':
|
||||
description: "Successful response"
|
||||
'400':
|
||||
description: "Bad Request - Incorrect request payload format"
|
||||
'401':
|
||||
description: "Unauthorized - Signature verification failed"
|
||||
'500':
|
||||
description: "Server error - Deployment process failed"
|
||||
26
infra/cfn/template-secret-key.yaml
Normal file
26
infra/cfn/template-secret-key.yaml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: AWS::Serverless-2016-10-31
|
||||
Parameters:
|
||||
WebhookSecret:
|
||||
Type: String
|
||||
Description: The number as a secret key of a webhook
|
||||
|
||||
Resources:
|
||||
|
||||
SecretForWebhook:
|
||||
Type: AWS::SecretsManager::Secret
|
||||
Properties:
|
||||
Description: The number as a secret key of a webhook
|
||||
SecretString: !Sub
|
||||
- '{"secretNumber": "${WebhookSecret}"}'
|
||||
- WebhookSecret: !Ref WebhookSecret
|
||||
Tags:
|
||||
- Key: Project
|
||||
Value: Git-server
|
||||
|
||||
Outputs:
|
||||
ArnSecretForWebhook:
|
||||
Description: ARN of secret key of a webhook
|
||||
Value: !Ref SecretForWebhook
|
||||
Export:
|
||||
Name: SecretForWebhook-ARN
|
||||
Loading…
Add table
Add a link
Reference in a new issue