Sitemap

Build a CI / CD Pipeline on AWS

9 min readNov 28, 2023

We will build a CI/CD Pipeline on AWS in this blog. We have all read in theory about the CI/CD pipeline, wouldn’t it be great if we were actually able to implement it? Let’s begin!

Press enter or click to view image in full size
Photo by Growtika on Unsplash

Pre Requisites

You will need the following to do this hands-on tutorial along with me.

  • AWS Account
  • AWS CodeCatalyst Account (linked to AWS ID)

I have used this tutorial as a reference.

1. Create IAM Role

First, we will proceed to create a new Stack in CloudFormation Stack.

Press enter or click to view image in full size

We need to apply this stack. Save the below code as a .json file. I have named mine codecatalyst.json

CloudFormation console > Create New Stack > Template > Upload a template
{
"AWSTemplateFormatVersion" : "2010-09-09",

"Description" : "AWS CloudFormation Template IAM_Role_and_Policies: Template to create 2 new service roles for CodeCatalyst - CloudFormation deployment. **WARNING** The `main_branch_IAM_role` provides full access to AWS resources in EC2 and CloudFormation services, as those will be used by sample CloudFormation template mentioned in the blog. Please use this role carefully and delete it when not required.",

"Resources" : {
"MainBranchRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": {
"Service": [
"codecatalyst.amazonaws.com",
"codecatalyst-runner.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
},
"Path": "/",
"RoleName" : "main_branch_IAM_role",
"Policies": [
{
"PolicyName": "ProvideAmazonEC2FullAccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "ec2:*",
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "elasticloadbalancing:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "cloudwatch:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "autoscaling:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": [
"autoscaling.amazonaws.com",
"ec2scheduled.amazonaws.com",
"elasticloadbalancing.amazonaws.com",
"spot.amazonaws.com",
"spotfleet.amazonaws.com",
"transitgateway.amazonaws.com"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"cognito-idp:DescribeUserPoolClient"
],
"Resource": "*"
}
]
}
},
{
"PolicyName": "ProvideAWSCloudFormationFullAccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudformation:*"
],
"Resource": "*"
}
]
}
}
]
}
},
"PRBranchRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": {
"Service": [
"codecatalyst.amazonaws.com",
"codecatalyst-runner.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
},
"Path": "/",
"RoleName" : "pr_branch_IAM_role",
"Policies": [
{
"PolicyName": "CloudFormation-PR-policy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"cloudformation:Describe*",
"cloudformation:CreateChangeSet",
"cloudformation:DeleteChangeSet",
"cloudformation:ExecuteChangeSet",
"cloudformation:SetStackPolicy",
"cloudformation:ValidateTemplate",
"cloudformation:List*",
"iam:PassRole"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
},
{
"PolicyName": "ProvideEC2ReadOnlyAccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ec2:Describe*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "elasticloadbalancing:Describe*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"cloudwatch:ListMetrics",
"cloudwatch:GetMetricStatistics",
"cloudwatch:Describe*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "autoscaling:Describe*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"sns:ListSubscriptions",
"sns:ListTopics"
],
"Resource": "*"
}
]
}
}
]
}
}
}
}
Press enter or click to view image in full size

If you click “view on designer”, you will see the following design.

Press enter or click to view image in full size

We have set the region to be us-west-2. Click on next and enter the stack name below.

CodeCatalyst-IAM-roles
Press enter or click to view image in full size

The architecture will be as shown below.

Press enter or click to view image in full size

Let the rest of the settings remain at default. Just provide the acknowledgement and hit Submit.

Press enter or click to view image in full size

The stack is now being created.

Press enter or click to view image in full size

Code Catalyst

AWS Code Catalyst is an integrated development environment (IDE) provided by Amazon Web Services (AWS) that aims to simplify the software development workflow. It combines a comprehensive set of tools, services, and resources, enabling developers to efficiently collaborate, build, test, and deploy applications within a unified environment.

Code Catalyst is fully managed by AWS, so developers can focus on development. It provides a cloud-based development environment that allows developers to rapidly iterate on code and improve their development productivity. It also simplifies the cross-account functionalities of continuous integration and delivery (CI/CD) best practices.

Code Catalyst offers a unified software development service that makes it faster to build and deliver software on AWS. You can learn more and get started building in minutes on the AWS Free Tier at the Code Catalyst website.

Log into Code Catalyst

Create a new space with any name. Mine is:

workspaceanish
Press enter or click to view image in full size

Verify in AWS

Press enter or click to view image in full size

Once the space is created, go to the AWS Accounts tab, click on your account ID, and then click on Manage roles from the AWS Management Console.

Press enter or click to view image in full size

Select your workspace

Press enter or click to view image in full size

Add IAM Role.

Press enter or click to view image in full size

Select the role we created previously.

main_branch_IAM_role
Press enter or click to view image in full size

Next, go back to CodeCatalyst and create a new Project and start from scratch.

Press enter or click to view image in full size

Start from Scratch

Press enter or click to view image in full size

Add Code Repository

Select Source Repository.

Source Reposiory > Add Repository > Create Repository > 3-tier-app
Press enter or click to view image in full size

Add the details for the repository as shown below.

Press enter or click to view image in full size
Press enter or click to view image in full size

Environment

Lastly, we need to set up the AWS environment where our CloudFormation stack will be deployed by automated workflows. This is my non-production environment where my sample CloudFormation template will be deployed.

From the left navigation panel, select CI/CD, Environments, and click on Create Environment. In the Environment details enter following:

  • Environment name: PreProdEnv
  • Environment type: Non-production
  • Description: Pre-production environment to learn, test and experiment with CloudFormation
  • AWS account connection
  • Connection: Select the AWS account ID that will be used in the workflows to deploy this environment
Press enter or click to view image in full size

Setting up a Dev Environment

We will use the IDE AWS Cloud9 for our development.

From the left navigation panel, select Code, Dev Environments, and click on Create Dev Environment. In the Create dev environment and open with AWS Cloud9 dialog box select following:

  • Repository: Clone a repository
  • Repository: Select the repo that you want to clone. We created a repo 3-tier-app above, so select same.
  • Branch: Work in existing branch
  • Alias: bootstrap
Press enter or click to view image in full size
Press enter or click to view image in full size

AWS Cloud9 IDE

You will now see the IDE.

Press enter or click to view image in full size

For this blog, I am using a sample template that deploys a VPC with 2 subnets and publicly accessible Amazon EC2 instances that are in an Auto Scaling group behind a Load Balancer form. Feel free to use the same as I will be making changes to this template and run a pull request workflow.

# go to the root folder of the repo and run following

$ cd 3-tier-app/
$ wget https://raw.githubusercontent.com/build-on-aws/ci-cd-iac-aws-cloudformation/main/cloudformation-templates/VPC_AutoScaling_With_Public_IPs.json

# check git status
$ git status

# add changed files, commit and push to the git repo
$ git add . -A
$ git commit -m "Uploading first CloudFormation template"
$ git push
Press enter or click to view image in full size

You can verify if the CloudFormation template is successfully updated in the repo — in the CodeCatalyst console, click Code in the left-side navigation menu, then select Source repositories. A new file VPC_AutoScaling_With_Public_IPs.json should be added to the repo.

Press enter or click to view image in full size

Set up Workflows to Deply Non-prod environment

Here, we will use the dev environment using yaml.

# go to the root folder of the repo and run following
mkdir -p .codecatalyst/workflows
touch .codecatalyst/workflows/main_branch.yaml

Open this in your IDE as shown in the image below.

3-tier-app > .codecatalyst > worflows > main_branch.yaml

Double click on main_branch.yaml

Press enter or click to view image in full size

I will give you the code to paste in the yaml file. Just make sure to replace the AWS ID with your AWS ID, which you can find in the home console.

You can find your AWS ID if you click on your name.

Name: Main_Branch_Workflow
SchemaVersion: "1.0"

# Optional - Set automatic triggers.
Triggers:
- Type: Push
Branches:
- main

# Required - Define action configurations.
Actions:
DeployAWSCloudFormationstack_7c:
Identifier: aws/cfn-deploy@v1
Configuration:
parameter-overrides: SSHLocation=54.10.10.2/32,WebServerInstanceType=t2.micro
capabilities: CAPABILITY_IAM,CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND
template: VPC_AutoScaling_With_Public_IPs.json
region: us-west-2
name: PreProdEnvStack
Timeout: 10
Environment:
Connections:
- Role: main_branch_IAM_role
Name: "123456789012" #Insert your AWS ID here (inside the double quotes) and remove the comment after #
Name: PreProdEnv
Inputs:
Sources:
- WorkflowSource

Let’s try out our new workflow

$ clear
$ git add . -A
$ git commit -m "Adding main branch workflow"
$ git push

In your browser, navigate to the CI/CD -> Workflows page. You should see the workflow running:

Press enter or click to view image in full size

If you click on the run, you will see the workflow.

Press enter or click to view image in full size

If you click on the workflow, you will see the steps for it to be deployed.

Press enter or click to view image in full size

It will take some time for CodeCatalyst to go through all the stages and deploy the CloudFormation stack. The stack deployment time depends on the resources defined in the template.

It will succeed in sometime.

Then, go to variables and copy the website.

See your successful output!

When you paste it on the browser, you will get the following:

Press enter or click to view image in full size

--

--

Anish Mahapatra
Anish Mahapatra

Written by Anish Mahapatra

Senior AI & ML Engineer | Fortune 500 | Senior Technical Writer - Google me. Anish Mahapatra | https://www.linkedin.com/in/anishmahapatra/

No responses yet