CI/CDとは
開発のプロセスを効率化し、ビルドやテスト、デプロイを自動化する手法です。
これにより、リリースまでの工数削減や手作業によるオペレーションミスを抑止することができます。
主なツールとしては以下のようなものが存在します。
- GitHub Actions
- GitLab CI/CD
- CircleCI
- AWS Codeシリーズ
CI/CDやってみる
構成
今回は以下のような構成で作成します。
特定リポジトリのmainブランチへPushするとパイプラインが起動し、公開S3バケットへファイルをデプロイする流れとなります。

デプロイの対象としてはHTMLファイルのみとするため、ビルドやテストは省略しています。
必要となる場合は、CodeBuildなどを追加することで実装できます。
検証
事前準備
事前準備として、以下を実施しておきます。
環境作成
事前準備が完了したら、S3やCodePipelineなどのAWSリソースを作成していきます。
なお、作成にはCloudFormationを利用します。
テンプレート
AWSTemplateFormatVersion: "2010-09-09"
Description: CICD Demo
Parameters:
CodeStarConnectionArn:
Type: String
Description: ARN of CodeStar Connection
Default: arn:aws:codestar-connections:ap-northeast-1:123456789012:connection/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
RepositoryId:
Type: String
Description: Code Repository ID
Default: github-user/repo-name
BranchName:
Type: String
Description: Branch Name
Default: main
Resources:
##############################
# S3 Bucket
##############################
WebsiteBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub 'cicd-website-bucket-${AWS::AccountId}'
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: false
IgnorePublicAcls: false
RestrictPublicBuckets: false
WebsiteConfiguration:
IndexDocument: index.html
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref WebsiteBucket
PolicyDocument:
Statement:
- Sid: PublicReadForGetBucketObjects
Effect: Allow
Principal: "*"
Action: "s3:GetObject"
Resource: !Sub 'arn:aws:s3:::${WebsiteBucket}/*'
ArtifactBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub 'cicd-artifact-bucket-${AWS::AccountId}'
##############################
# IAM
##############################
CodePipelineServiceRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub CodePipeline-Service-Role-${AWS::Region}
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- codepipeline.amazonaws.com
Action:
- sts:AssumeRole
Path: /
CodePipelineServiceRolePolicy:
Type: AWS::IAM::RolePolicy
Properties:
RoleName: !Ref CodePipelineServiceRole
PolicyName: CodePipelineServicePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:PutObject*
- s3:DeleteObject*
- s3:Abort*
Resource:
- !Sub 'arn:aws:s3:::${ArtifactBucket}'
- !Sub 'arn:aws:s3:::${ArtifactBucket}/*'
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- !GetAtt PipelineSourceRole.Arn
- !GetAtt PipelineActionRole.Arn
PipelineSourceRole:
Type: AWS::IAM::Role
DependsOn:
- CodePipelineServiceRole
Properties:
RoleName: !Sub CodePipeline-Source-Role-${AWS::Region}
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:role/CodePipeline-Service-Role-${AWS::Region}'
Action:
- sts:AssumeRole
Policies:
- PolicyName: CodePipelineSourcePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:PutObject*
- s3:DeleteObject*
- s3:Abort*
Resource:
- !Sub 'arn:aws:s3:::${ArtifactBucket}'
- !Sub 'arn:aws:s3:::${ArtifactBucket}/*'
- Effect: Allow
Action:
- codestar-connections:UseConnection
Resource:
- !Sub 'arn:aws:codeconnections:${AWS::Region}:${AWS::AccountId}:connection/*'
Path: /
PipelineActionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub CodePipeline-Action-Role-${AWS::Region}
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:role/CodePipeline-Service-Role-${AWS::Region}'
Action:
- sts:AssumeRole
Policies:
- PolicyName: CodePipelineActionPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:PutObject*
- s3:DeleteObject*
- s3:Abort*
Resource:
- !Sub 'arn:aws:s3:::${ArtifactBucket}'
- !Sub 'arn:aws:s3:::${ArtifactBucket}/*'
- !Sub 'arn:aws:s3:::${WebsiteBucket}'
- !Sub 'arn:aws:s3:::${WebsiteBucket}/*'
Path: /
##############################
# CodePipeline
##############################
CICDPipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: cicd-s3-pipeline
PipelineType: V2
RoleArn: !GetAtt CodePipelineServiceRole.Arn
ArtifactStore:
Type: S3
Location: !Ref ArtifactBucket
Stages:
- Name: Source
Actions:
- Name: SourceAction
RunOrder: 1
RoleArn: !GetAtt PipelineSourceRole.Arn
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeStarSourceConnection
Version: '1'
Configuration:
ConnectionArn: !Ref CodeStarConnectionArn
FullRepositoryId: !Ref RepositoryId
BranchName: !Ref BranchName
OutputArtifacts:
- Name: SourceOutput
- Name: Deploy
Actions:
- Name: DeployAction
RunOrder: 1
RoleArn: !GetAtt PipelineActionRole.Arn
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: S3
Version: '1'
Configuration:
BucketName: !Ref WebsiteBucket
Extract: 'true'
InputArtifacts:
- Name: SourceOutput
※利用する際はスタック作成時のパラメータに事前準備で作成したものを入力ください。
下図のようにCREATE_COMPLEATEと表示されたら正常に作成完了です。

リソースの作成ができたら、実際にWebブラウザからアクセスしてみます。
今回は事前準備の際に、以下のindex.htmlファイルを格納していますので、Hello, World!と表示されるはずです。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cicdデモ</title>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
なお、ブラウザに入力するURLは作成されたS3バケットの プロパティ > 静的ウェブサイトホスティングから確認が可能です。

CI/CDの確認
環境の作成ができたところで、任意のエディタからindex.htmlを編集し、Webページの表示が変更されることを確認していきましょう。
Hello, World!としていた箇所をHello, CI/CD!に変更し、mainブランチへプッシュします。

Webブラウザからアクセスすると、変更した箇所が反映されていました!

環境削除
検証用に作成した環境はCloudFormationのスタック削除から実施します。
S3にファイルが格納されたままだと削除時にエラーになるため、事前に空にしておきましょう。
まとめ
通常であれば、今回のケースであればindex.htmlを変更してGitHubに同期しS3にも手動でアップロード…といった手順が必要になります。
1ファイルならまだよいですが、ファイルが多ければ多いほど面倒です。
さらに、ビルドやテストも実行するとなるとその都度工数が発生します。
CI/CD環境を整えておくと、工数が短縮され、手作業でのミスも抑止されるため進んで導入していきたいなと感じました。

