Automating AWS CodeCommit With CloudFormation
Recently, AWS announced that you can now automate the provisioning of a hosted Git repository with AWS CodeCommit using CloudFormation.
Join the DZone community and get the full member experience.
Join For FreeRecently, AWS announced that you can now automate the provisioning of a hosted Git repository with AWS CodeCommit using CloudFormation. This means that in addition to the console, CLI, and SDK, you can use declarative code to provision a new CodeCommit repository — providing greater flexibility in versioning, testing, and integration.
In this post, I’ll describe how engineers can provision a CodeCommit Git repository in a CloudFormation template. Furthermore, you’ll learn how to automate the provisioning of a deployment pipeline that uses this repository as its Source action to deploy an application using CodeDeploy to an EC2 instance. You’ll see examples, patterns, and a short video that walks you through the process.
Prerequisites
Here are the prerequisites for this solution:
- AWS Account: Follow these instructions to create an AWS Account: Creating an AWS Account.
- EC2 Key Pair: Follow these instructions to create an EC2 Key Pair: Creating Your Key Pair Using Amazon EC2.
These will be explained in greater detail in the Deployment Steps section.
Architecture and Implementation
In the figure below, you see the architecture for launching a pipeline that deploys software to an EC2 instance from code stored in a CodeCommit repository. You can click on the image to launch the template in CloudFormation Designer.
- CloudFormation: All of the resource generation of this solution is described in CloudFormation which is a declarative code language that can be written in JSON or YAML.
- CodeCommit: With the addition of the AWS::CodeCommit::Repository resource, you can define your CodeCommit Git repositories in CloudFormation.
- CodeDeploy: CodeDeploy automates the deployment to the EC2 instance that was provisioned by the nested stack.
- CodePipeline: I’m defining CodePipeline’s stages and actions in CloudFormation code which includes using CodeCommit as a Source action and CodeDeploy for a Deploy action (For more information, see Action Structure Requirements in AWS CodePipeline).
- EC2: A nested CloudFormation stack is launched to provision a single EC2 instance on which the CodeDeploy agent is installed. The CloudFormation template called through the nested stack is provided by AWS.
- IAM: An Identity and Access Management (IAM) Role is provisioned via CloudFormation which defines the resources that the pipeline can access.
- SNS: A Simple Notification Service (SNS) Topic is provisioned via CloudFormation. The SNS topic is used by the CodeCommit repository for notifications.
CloudFormation Template
In this section, I’ll show code snippets from the CloudFormation template that provisions the entire solution. The focus of my samples is on the CodeCommit resources. There are several other resources defined in this template including EC2, IAM, SNS, CodePipeline, and CodeDeploy. You can find a link to the template at the bottom of this post.
CodeCommit
In the code snippet below, you see that I’m using the AWS::CodeCommit::Repository CloudFormation resource. The repository name is provided as parameter to the template. I created a trigger to receive notifications when the master branch gets updated using an SNS Topic as a dependent resource that is created in the same CloudFormation template. This is based on the sample code provided by AWS.
"MyRepo":{
"Type":"AWS::CodeCommit::Repository",
"DependsOn":"MySNSTopic",
"Properties":{
"RepositoryName":{
"Ref":"RepoName"
},
"RepositoryDescription":"CodeCommit Repository",
"Triggers":[
{
"Name":"MasterTrigger",
"CustomData":{
"Ref":"AWS::StackName"
},
"DestinationArn":{
"Ref":"MySNSTopic"
},
"Events":[
"all"
]
}
]
}
},
CodePipeline
In this CodePipeline snippet, you see how I’m using the CodeCommit repository resource as an input for the Source action in CodePipeline. In doing this, it polls the CodeCommit repository for any changes. When it discovers changes, it initiates an instance of the deployment pipeline in CodePipeline.
"Stages":[
{
"Name":"Source",
"Actions":[
{
"InputArtifacts":[
],
"Name":"Source",
"ActionTypeId":{
"Category":"Source",
"Owner":"AWS",
"Version":"1",
"Provider":"CodeCommit"
},
"OutputArtifacts":[
{
"Name":"MyApp"
}
],
"Configuration":{
"BranchName":{
"Ref":"RepositoryBranch"
},
"RepositoryName":{
"Ref":"RepoName"
}
},
"RunOrder":1
}
]
},
You can see an illustration of this pipeline in the figure below.
Costs
Since costs can vary widely in using certain AWS services and other tools, I’ve provided a cost breakdown and some sample scenarios to give you an idea of what your monthly spend might look like. The AWS Cost Calculator can assist in establishing cost projections.
- CloudFormation: No additional cost.
- CodeCommit: If you’re using on small project of less than six users, there’s no additional cost. See AWS CodeCommit Pricing for more information.
- CodeDeploy: No additional cost.
- CodePipeline: $1 a month per pipeline unless you’re using it as part of the free tier. For more information, see AWS CodePipeline pricing.
- EC2: Approximately $15/month if you’re running once t1.micro instance 24/7. See AWS EC2 Pricing for more information.
- IAM: No additional cost.
- SNS: Considering you probably won’t have over 1 million Amazon SNS requests for this particular solution, there’s no cost. For more information, see AWS SNS Pricing.
So, for this particular sample solution, you’ll spend around $16/month iff you run the EC2 instance for an entire month. If you just run it once and terminate it, you’ll spend a little over $1.
Patterns
Here are some patterns to consider when using CodeCommit with CloudFormation.
- CodeCommit Template: While this solution embeds the CodeCommit creation as part of a single CloudFormation template, it’s unlikely you’ll be updating the CodeCommit repository generation with every application change so you might create a template that focuses on the CodeCommit creation and run it as part of an infrastructure pipeline that gets updated when new CloudFormation is committed to it.
- Centralized Repos: Most likely, you’ll want to host your CodeCommit repositories in a single AWS account and use cross-account IAM roles to share access across accounts in your organization. While you can create CodeCommit repos in any AWS account, it’ll likely lead to unnecessary complexity when engineers want to know where the code is located.
The last is more of a conundrum than a pattern. As one my colleagues posted in Slack:
I’m stuck in a recursive loop…where do I store my CloudFormation template for my CodeCommit repo?
Good question. I don’t have a good answer for that one just yet. Anyone have thoughts on this one? It gets very “meta.”
Deployment Steps
There are three main steps in launching this solution: preparing an AWS account, launching the stack, and testing the deployment. Each is described in more detail in this section.
Step 1: Prepare an AWS Account
- If you don’t already have an AWS account, create one at http://aws.amazon.com by following the on-screen instructions. Part of the sign-up process involves receiving a phone call and entering a PIN using the phone keypad. Be sure you’ve signed up for the CloudFormation service.
- Use the region selector in the navigation bar of the console to choose the Northern Virginia (us-east-1) region
- Create a key pair. To do this, in the navigation pane of the Amazon EC2 console, choose Key Pairs, Create Key Pair, type a name, and then choose Create.
Step 2. Launch the Stack
Click on the Launch Stack button below to launch the CloudFormation stack. Before you launch the stack, review the architecture, configuration, security, and other considerations discussed in this post. To download the template, click here.
Time to deploy: Approximately seven minutes.
The template includes default settings that you can customize by following the instructions in this post.
Create Details
Here’s a listing of the key AWS resources that are created when this stack is launched:
- IAM: InstanceProfile, Policy, and Role.
- CodeCommit Repository: Hosts the versioned code.
- EC2 instance: with CodeDeploy agent installed.
- CodeDeploy: application and deployment.
- CodePipeline: deployment pipeline with CodeCommit Integration.
CLI Example
Alternatively, you can launch the same stack from the command line as shown in the samples below.
Base Command
From an instance that has the AWS CLI installed, you can use the following snippet as a base command prepended to one of two options described in the Parameters section below.
aws cloudformation create-stack --profile {AWS Profile Name} --stack-name {Stack Name} --capabilities CAPABILITY_IAM --template-url "https://s3.amazonaws.com/stelligent-public/cloudformation-templates/github/labs/codecommit/codecommit-cpl-cfn.json"
Parameters
I’ve provided two ways to run the command – from a custom parameters file or from the CLI.
Option 1: Custom Parameters JSON File
By attaching the command below to the base command, you can pass parameters from a file as shown in the sample below.
--parameters file:///localpath/to/example-parameters-cpl-cfn.json
Option 2: Pass Parameters on CLI
Another way to launch the stack from the command line is to provide custom parameters populated with parameter values as shown in the sample below.
--parameters ParameterKey=EC2KeyPairName,ParameterValue=stelligent-dev ParameterKey=EmailAddress,ParameterValue=jsmith@example.com ParameterKey=RepoName,ParameterValue=my-cc-repo
Step 3: Test the Deployment
Click on the CodePipelineURL Output in your CloudFormation stack. You’ll see that the pipeline has failed on the Source action. This is because the Source action expects a populated repository and it’s empty. The way to resolve this is to commit the application files to the newly-created CodeCommit repository. First, you’ll need to clone the repository locally. To do this, get the CloneUrlSsh Output from the CloudFormation stack you launched in Step 2. A sample command is shown below. You’ll replace {CloneUrlSsh} with the value from the CloudFormation stack output. For more information on using SSH to interact with CodeCommit, see the Connect to the CodeCommit Repository section at: Create and Connect to an AWS CodeCommit Repository.
git clone {CloneUrlSsh}
cd {localdirectory}
Once you’ve cloned the repository locally, download the sample application files from SampleApp_Linux.zip and place the files directly into your local repository. Do not include the SampleApp_Linux folder. Go to the local directory and type the following to commit and push the new files to the CodeCommit repository:
git add .
git commit -am "add all files from the AWS sample linux codedeploy application"
git push
Once these files have been committed, the pipeline will discover the changes in CodeCommit and run a new pipeline instance and both stages and actions should succeed as a result of this change.
Access the Application
Once the CloudFormation stack has successfully completed, go to CodeDeploy and select Deployments. For example, if you’re in the us-east-1 region, the URL might look like: https://console.aws.amazon.com/codedeploy/home?region=us-east-1#/deployments (You can also find this link in the CodeDeployURL Output of the CloudFormation stack you launched). Next, click on the link for the Deployment Id of the deployment you just launched from CloudFormation. Then, click on the link for the Instance Id. From the EC2 instance, copy the Public IP value and paste into your browser and hit enter. You should see a page like the one below.
Commit Changes to CodeCommit
Make some visual changes to the index.html (look for background-color) and commit these changes to your CodeCommit repository to see these changes get deployed through your pipeline. You perform these actions from the directory where you cloned the local version of your CodeCommit repo (in the directory created by your git clone command). To push these changes to the remote repository, see the commands below.
git commit -am "change bg color to burnt orange"
git push
Once these changes have been committed, CodePipeline will discover the changes made to your CodeCommit repo and initiate a new pipeline. After the pipeline is successfully completed, follow the same instructions for launching the application from your browser. You’ll see that the color of the index page of the application has changed.
How-To Video
In this video, I walk through the deployment steps described above.
Additional Resources
Here are some additional resources you might find useful:
- CloudFormation CodeCommit Resource Documentation.
- Create and Connect to an AWS CodeCommit Repository.
- Download the sample application that uses CodeDeploy from https://s3.amazonaws.com/aws-codedeploy-us-east-1/samples/latest/SampleApp_Linux.zip.
- Simple Pipeline Walkthrough (AWS CodeCommit Repository).
- CloudFormation template to launch up to three EC2 instances for CodeDeploy (this template is embedded in the sample code).
- CloudFormation SNS Topic Resource Documentation.
Summary
In this post, you learned how to define and launch a stack capable of launching a CloudFormation stack that provisions a CodeCommit Git repository in code. Additionally, the example included the automation of a CodePipeline deployment pipeline (which included the CodeCommit integration) along with creating and running the deployment on an EC2 instance using CodeDeploy.
Furthermore, I described the prerequisites, architecture, implementation, costs, patterns and deployment steps of the solution.
Sample Code
The code for the examples demonstrated in this post are located at https://github.com/stelligent/cloudformation_templates/blob/master/labs/codecommit/. Let us know if you have any comments or questions @stelligent or @paulduvall.
Published at DZone with permission of Paul Duvall, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments