I am very new to Cloudformation and I have a (maybe) stupid question. Here goes.
I want to describe my pipelines with cloudformation templates, which i commit to a repository (just for cloudformation templates).
Then i create a pipeline, that deploys the templates, and with that create the pipelines for the different apps.
This is currently working, but I have one issue: I can't connect to an existing repository. I can only figure out how to create a new repository within the stack, and use that repository in the pipeline. Se below template.
I have seen examples of people connection to github, doing something like this, and I would like to know if this is possible also with Codecommit. The issue is of course, that if you delete your cloudformation stack, you also delete your repository. And if you have an existing repository with your app, it gets gritty.
So is this possible, or have I misunderstood something (remember, I am new to this).
AWSTemplateFormatVersion: 2010-09-09
Resources:
CodePipeline:
Type: 'AWS::CodePipeline::Pipeline'
Properties:
RoleArn: !GetAtt CodePipeLineRole.Arn
ArtifactStore:
Location: !Ref PipelineBucket
Type: S3
Stages:
-
Name: Source
Actions:
- Name: CheckoutSourceTemplate
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
Configuration:
PollForSourceChanges: true
RepositoryName: !GetAtt
- PipelineRepo
- Name
BranchName: master
OutputArtifacts:
- Name: MyApp
RunOrder: 1
-
Name: Build
Actions:
-
Name: BuildAction
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
InputArtifacts:
-
Name: MyApp
OutputArtifacts:
-
Name: MyAppBuild
Configuration:
ProjectName: !Ref CodeBuild
PipelineRepo:
Type: 'AWS::CodeCommit::Repository'
Properties:
RepositoryName: evenz-react-app
RepositoryDescription: Pipeline repository
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: Allow
Principal:
Service:
- "codebuild.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: /service-role/
Policies:
- PolicyName: root
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: Allow
Action:
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:GetBucketVersioning"
- "s3:PutObject"
Resource:
- !GetAtt PipelineBucket.Arn
- !Join ['', [!GetAtt PipelineBucket.Arn, "/*"]]
-
Effect: Allow
Action:
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:GetBucketVersioning"
- "s3:PutObject"
- "s3:PutObjectAcl"
Resource:
- !GetAtt DeployBucket.Arn
- !Join ['', [!GetAtt DeployBucket.Arn, "/*"]]
-
Effect: Allow
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "cloudfront:CreateInvalidation"
Resource:
- "*"
CodePipeLineRole:
Type: AWS::IAM::Role
Properties:
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:
-
Effect: Allow
Action:
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:GetBucketVersioning"
- "s3:PutObject"
Resource:
- !GetAtt PipelineBucket.Arn
- !Join ['', [!GetAtt PipelineBucket.Arn, "/*"]]
-
Effect: Allow
Action:
- "codebuild:BatchGetBuilds"
- "codebuild:StartBuild"
Resource: "*"
-
Effect: Allow
Action:
- "codecommit:GetRepository"
- "codecommit:ListRepositories"
- "codecommit:GetBranch"
- "codecommit:GetCommit"
- "codecommit:UploadArchive"
- "codecommit:GetUploadArchiveStatus"
Resource: "*"
CodeBuild:
Type: 'AWS::CodeBuild::Project'
Properties:
Name: !Sub ${AWS::StackName}-CodeBuild
ServiceRole: !GetAtt CodeBuildRole.Arn
Artifacts:
Type: CODEPIPELINE
Name: MyProject
Source:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Type: LINUX_CONTAINER
Image: "aws/codebuild/nodejs:8.11.0"
Source:
Type: CODEPIPELINE
BuildSpec: !Sub |
version: 0.1
phases:
pre_build:
commands:
- echo Installing source NPM dependencies...
- npm install
build:
commands:
- echo Build started on `date`
- npm run build
post_build:
commands:
- aws s3 cp --recursive --acl public-read ./build s3://${DeployBucket}/
- aws s3 cp --acl public-read --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/service-worker.js s3://${DeployBucket}/
- aws s3 cp --acl public-read --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/index.html s3://${DeployBucket}/
- aws cloudfront create-invalidation --distribution-id ${Distribution} --paths /index.html /service-worker.js
artifacts:
files:
- '**/*'
base-directory: build
PipelineBucket:
Type: 'AWS::S3::Bucket'
Properties: {}
DeployBucket:
Type: 'AWS::S3::Bucket'
Properties:
WebsiteConfiguration:
IndexDocument: index.html
Distribution:
Type: "AWS::CloudFront::Distribution"
Properties:
DistributionConfig:
Origins:
-
DomainName: !GetAtt DeployBucket.DomainName
Id: !Ref DeployBucket
S3OriginConfig:
OriginAccessIdentity: ''
DefaultRootObject: index.html
Enabled: true
DefaultCacheBehavior:
MinTTL: 86400
MaxTTL: 31536000
ForwardedValues:
QueryString: true
TargetOriginId: !Ref DeployBucket
ViewerProtocolPolicy: "redirect-to-https"
UPDATE:
Thanks to the answer from Marcin below, I changed the reference to the repository to a parameter instead of AWS::CodeCommit::Repository
, which works perfectly like I was looking for. The full template now looks like this:
AWSTemplateFormatVersion: 2010-09-09
Parameters:
PipelineRepo:
Type: String
Default: evenz-react-app
Description: "Codecommit repo name"
Resources:
CodePipeline:
Type: 'AWS::CodePipeline::Pipeline'
Properties:
RoleArn: !GetAtt CodePipeLineRole.Arn
ArtifactStore:
Location: !Ref PipelineBucket
Type: S3
Stages:
-
Name: Source
Actions:
- Name: CheckoutSourceTemplate
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
Configuration:
PollForSourceChanges: true
RepositoryName: !Ref PipelineRepo
BranchName: master
OutputArtifacts:
- Name: MyApp
RunOrder: 1
-
Name: Build
Actions:
-
Name: BuildAction
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
InputArtifacts:
-
Name: MyApp
OutputArtifacts:
-
Name: MyAppBuild
Configuration:
ProjectName: !Ref CodeBuild
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: Allow
Principal:
Service:
- "codebuild.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: /service-role/
Policies:
- PolicyName: root
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: Allow
Action:
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:GetBucketVersioning"
- "s3:PutObject"
Resource:
- !GetAtt PipelineBucket.Arn
- !Join ['', [!GetAtt PipelineBucket.Arn, "/*"]]
-
Effect: Allow
Action:
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:GetBucketVersioning"
- "s3:PutObject"
- "s3:PutObjectAcl"
Resource:
- !GetAtt DeployBucket.Arn
- !Join ['', [!GetAtt DeployBucket.Arn, "/*"]]
-
Effect: Allow
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "cloudfront:CreateInvalidation"
Resource:
- "*"
CodePipeLineRole:
Type: AWS::IAM::Role
Properties:
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:
-
Effect: Allow
Action:
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:GetBucketVersioning"
- "s3:PutObject"
Resource:
- !GetAtt PipelineBucket.Arn
- !Join ['', [!GetAtt PipelineBucket.Arn, "/*"]]
-
Effect: Allow
Action:
- "codebuild:BatchGetBuilds"
- "codebuild:StartBuild"
Resource: "*"
-
Effect: Allow
Action:
- "codecommit:GetRepository"
- "codecommit:ListRepositories"
- "codecommit:GetBranch"
- "codecommit:GetCommit"
- "codecommit:UploadArchive"
- "codecommit:GetUploadArchiveStatus"
Resource: "*"
CodeBuild:
Type: 'AWS::CodeBuild::Project'
Properties:
Name: !Sub ${AWS::StackName}-CodeBuild
ServiceRole: !GetAtt CodeBuildRole.Arn
Artifacts:
Type: CODEPIPELINE
Name: MyProject
Source:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Type: LINUX_CONTAINER
Image: "aws/codebuild/nodejs:8.11.0"
Source:
Type: CODEPIPELINE
BuildSpec: !Sub |
version: 0.1
phases:
pre_build:
commands:
- echo Installing source NPM dependencies...
- npm install
build:
commands:
- echo Build started on `date`
- npm run build
post_build:
commands:
- aws s3 cp --recursive --acl public-read ./build s3://${DeployBucket}/
- aws s3 cp --acl public-read --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/service-worker.js s3://${DeployBucket}/
- aws s3 cp --acl public-read --cache-control="max-age=0, no-cache, no-store, must-revalidate" ./build/index.html s3://${DeployBucket}/
- aws cloudfront create-invalidation --distribution-id ${Distribution} --paths /index.html /service-worker.js
artifacts:
files:
- '**/*'
base-directory: build
PipelineBucket:
Type: 'AWS::S3::Bucket'
Properties: {}
DeployBucket:
Type: 'AWS::S3::Bucket'
Properties:
WebsiteConfiguration:
IndexDocument: index.html
Distribution:
Type: "AWS::CloudFront::Distribution"
Properties:
DistributionConfig:
Origins:
-
DomainName: !GetAtt DeployBucket.DomainName
Id: !Ref DeployBucket
S3OriginConfig:
OriginAccessIdentity: ''
DefaultRootObject: index.html
Enabled: true
DefaultCacheBehavior:
MinTTL: 86400
MaxTTL: 31536000
ForwardedValues:
QueryString: true
TargetOriginId: !Ref DeployBucket
ViewerProtocolPolicy: "redirect-to-https"
Maybe I misunderstood the issue, but I think that the separation of your PipelineRepo
into its own template and stack would be helpful.
You could create a simple template for only the PipelineRepo
which exports the RepoName
e.g.
Resources:
PipelineRepo:
Type: 'AWS::CodeCommit::Repository'
Properties:
RepositoryName: evenz-react-app
RepositoryDescription: Pipeline repository
Outputs:
RepoName:
Value: !GetAtt PipelineRepo.Name
Export:
Name: RepoName
Then you would use ImportValue to import it:
Configuration:
PollForSourceChanges: true
RepositoryName: !ImportValue RepoName
Subsequently, the lifecycle of your PipelineRepo
is not tided with the stack of your CodePipeline. CodePipeline stack can be deleted and re-created at anytime, without affecting the PipelineRepo
.
p.s.
You may hear about importing existing resources into CloudFormation. Normally, this could be considered in a similar case to yours, but AWS::CodeCommit::Repository
is not supported for such imports.