dev ドメインで作成したブログのパイプラインを作成する
概要
前の記事でブログをホスティングするための環境を作成しました。 この記事ではブログを継続的にデプロイするためのパイプライラインを作成します。
前提
- ブログ記事の管理は Github
テンプレート
作成するリソースは大体次です。
- ブログをビルドするための CodeBuild
- ソースが Github、ビルドが前述の CodeBuild、デプロイが S3 の CodePipeline
- Github からの変更を通知する WebHook
- WebHook のシークレット
入力パラメーター
GitHubRepo
にはブログを管理してる Github のリポジトリ名GitHubBranch
にはそのブランチ名(例:master
)GitHubToken
には Github の OAuth トークン。個人用のアクセストークンを使用するようにパイプラインを設定する (GitHub と CLI)GitHubUser
には Github のユーザ名DeployBucket
には、前の記事で作成した CloudFront のオリジンの S3 バケット名(例: www.konoui.dev)DistributionID
には、前の記事で作成した CloudFront のディストリビューション ID
この内、DistributionID
ですが、これは、CodeBuild 内で、CloudFront のキャッシュを Invalidation するために使用します。
buildspec.yml ファイルも添付します。hugo でビルドしています。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
GitHubRepo:
Type: String
GitHubBranch:
Type: String
GitHubToken:
Type: String
NoEcho: true
GitHubUser:
Type: String
SourceArtifact:
Type: String
Default: SourceArtifact
BuildArtifact:
Type: String
Default: BuildArtifact
DeployBucket:
Type: String
DistributionID:
Type: String
Resources:
ArtifactBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
LifecycleConfiguration:
Rules:
- Id: delete all objects per a day
Status: Enabled
ExpirationInDays: 1
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Artifacts:
Type: CODEPIPELINE
Source:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:1.0
Type: LINUX_CONTAINER
PrivilegedMode: True
EnvironmentVariables:
- Name: AWS_ACCOUNT_ID
Value: !Ref AWS::AccountId
- Name: AWS_DEFAULT_REGION
Value: !Ref AWS::Region
- Name: DISTRIBUTION_ID
Value: !Ref DistributionID
- Name: DEPLOY_BUCKET
Value: !Ref DeployBucket
Name: !Ref AWS::StackName
# does not work on CodePipeline
# BadgeEnabled: True
ServiceRole: !Ref CodeBuildServiceRole
CodeBuildServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource: "*"
Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Resource: !Sub arn:aws:s3:::${ArtifactBucket}/*
Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
- s3:GetObjectVersion
ManagedPolicyArns:
- arn:aws:iam::aws:policy/PowerUserAccess
- arn:aws:iam::aws:policy/IAMReadOnlyAccess
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
RoleArn: !GetAtt CodePipelineServiceRole.Arn
ArtifactStore:
Type: S3
Location: !Ref ArtifactBucket
Stages:
- Name: Source
Actions:
- Name: Github
ActionTypeId:
Category: Source
Owner: ThirdParty
Version: 1
Provider: GitHub
Configuration:
Owner: !Ref GitHubUser
Repo: !Ref GitHubRepo
Branch: !Ref GitHubBranch
OAuthToken: !Ref GitHubToken
PollForSourceChanges: false
OutputArtifacts:
- Name: !Ref SourceArtifact
RunOrder: 1
- Name: Build
Actions:
- Name: Build
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
Configuration:
ProjectName: !Ref CodeBuildProject
InputArtifacts:
- Name: !Ref SourceArtifact
OutputArtifacts:
- Name: !Ref BuildArtifact
RunOrder: 1
- Name: Deploy
Actions:
- Name: DeployAction
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: S3
Version: 1
InputArtifacts:
- Name: !Ref BuildArtifact
Configuration:
BucketName: !Ref DeployBucket
Extract: true
RunOrder: 1
CodePipelineServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource:
- !Sub arn:aws:s3:::${ArtifactBucket}/*
Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:GetObjectVersion
- s3:GetBucketVersioning
- Resource: "*"
Effect: Allow
Action:
- codebuild:StartBuild
- codebuild:BatchGetBuilds
- Resource:
- !Sub arn:aws:s3:::${DeployBucket}/*
Effect: Allow
Action:
- s3:PutObject
- s3:PutObjectAcl
- s3:PutObjectVersionAcl
GitHubSecret:
Type: AWS::SecretsManager::Secret
Properties:
GenerateSecretString:
SecretStringTemplate: "{}"
GenerateStringKey: "SecretToken"
ExcludePunctuation: true
PasswordLength: 40
PipelineWebhook:
Type: AWS::CodePipeline::Webhook
Properties:
Authentication: GITHUB_HMAC
AuthenticationConfiguration:
SecretToken: !Sub "{{resolve:secretsmanager:${GitHubSecret}:SecretString:SecretToken}}"
Filters:
- JsonPath: "$.ref"
MatchEquals: refs/heads/{Branch}
TargetPipeline: !Ref Pipeline
TargetAction: Github
TargetPipelineVersion: !GetAtt Pipeline.Version
RegisterWithThirdParty: true
Outputs:
PipelineUrl:
Value: !Sub https://console.aws.amazon.com/codepipeline/home?region=${AWS::Region}#/view/${Pipeline}
version: 0.2
env:
variables:
HUGO_VERSION: "0.59.1"
phases:
install:
runtime-versions:
golang: 1.13
commands:
- curl -Ls https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_Linux-64bit.tar.gz -o /tmp/hugo.tar.gz
- tar xf /tmp/hugo.tar.gz -C /tmp
- mv /tmp/hugo /usr/bin/hugo
build:
commands:
- hugo
post_build:
commands:
# - aws s3 sync --delete public/ s3://${DEPLOY_BUCKET}
- aws cloudfront create-invalidation --distribution-id ${DISTRIBUTION_ID} --paths "/*" --region ${AWS_DEFAULT_REGION}
artifacts:
files:
- "**/*"
base-directory: public
name: page-$(date +%Y-%m-%d)
備考
S3 への Deploy ステージ使わずに、CodeBuild 内で aws s3 sync すれば良いのではないかと思われるかもしれませんが、個人的にはその通りかなと思います。 CodeBuild で S3 にデプロイする方法のメリットは、1. aws s3 sync –delete オプションで不要なファイルを削除できる。2. CloudFront のキャッシュを Invalidation するタイミングがベストである点が挙げられます。 特に、Invalidation はデプロイステージ後に行うことで、確実となりますが、この例では、デプロイ前に行うことになるため、タイミング的に最新のデプロイが反映されない可能性が挙げられます。 ではなぜデプロイステージで S3 をするかですが、それはやってみたかったからとなります。その他、メリットがあればご指摘ください。