What is CICD?
CI/CD stands for Continuous Integration and Continuous Deployment/Delivery. It’s a practice in software development that automates the process of integrating code changes, testing, and deploying them to production.
Example:
In a CI/CD pipeline, when a developer pushes code to a GitHub repository, an automated system like Jenkins builds the code, runs tests, and if all checks pass, deploys the new version to a live website without manual intervention.
Getting started :
The goal of this article is to guide you through a practical example of what it looks like when you’re deploying applications with AWS.
Here are the steps tailored to the application we’re deploying, specifically a NodeJS
application (NodeJS version 18 and above).
AWS Services used :
EC2
S3
VPC
IAM
CloudFormation
CodeCommit
CodeBuild
CodeDeploy
CodePipeline
Lets Begin :
Step 1 : CodeCommit
AWS CodeCommit is a managed source control service by AWS that allows users to store, manage, and version their source code and artifacts securely and at scale just like what GitHub does.
Step 2: Setting up git credentials in your AWS IAM
In the ‘HTTPS Git credentials for AWS CodeCommit’ section, click on ‘Generate credentials’.
Further, download these credentials and, you will be prompted to enter your Git credentials. Enter the username and password that you downloaded earlier.
Step 3: Commit your project to CodeCommit repository
Navigate to the directory where you want to clone the repository. Run the following command:
git clone <your-codecommit-repo-clone-https-url>
Put your code in this cloned repository. Push the changes from your local branch to the CodeCommit repository using the following command:
git push origin master
Verify that the changes have been pushed to the CodeCommit repository.
Step 4: Create S3 Bucket
Enter a Bucket name, and choose the Region where you want to create the bucket. In the Block Public Access settings for this bucket section, uncheck the box for Block all public access. Leave the other settings as and create the bucket by clicking on Create bucket.
Verify that the bucket is created successfully, we use this bucket to store our artifacts.
As you can see our S3 bucket has been successfully created. Now, let’s dive into our AWS CodeBuild service.
Step 5: CodeBuild
Heading to the AWS CodeBuild service, create a build project as shown below. Specify the project name of your choice.
Now select the source provider as AWS CodeCommit as we have stored the project files in the CodeCommit repository. Select the repository with the dropdown option.
Keep the environment settings as default. Moving ahead select a new service role and give name to it , keep the other settings as it is.
In the build specifications, we will be using our buildspec.yml file. Specify the name of buildspec file.
NOTE: The buildspec.yml file has to be stored in the CodeCommit repository.
Following is the buildspec.yml file we have used in our project:
version: 0.2
phases:
install:
runtime-versions:
nodejs: 18
pre_build:
commands:
- echo "Installing Node.js dependencies..."
- npm install
build:
commands:
- echo "Building Node.js application..."
- npm run build
post_build:
commands:
- echo "Build completed successfully!"
artifacts:
files:
- build/** # Adjust the output directory if different
- deploy_scripts/*.sh
- appspec.yml
discard-paths: yes
Now under the artifacts section, select Amazon S3 as the artifact type and select the bucket name that we had created under the Bucket Name. Also, give a folder name to store the build artifacts inside the bucket.
NOTE: Use artifact packaging as a .zip
Leave the rest of the configurations as default and click Create build project. Once you click Create Build Project, you will be redirected to the new interface where you can start building a project.
The duration of the build may vary depending on the configurations in your buildspec.yml file.
The project has been successfully built, confirmed by the success status across all phases. Our build is completed successfully!
Now, let’s see if our build artifacts are stored in our S3 bucket or not.
Step 6: Setting up the infrastructure
We have launched the infrastructure with the help of the AWS CloudFormation Template. Automation helps us improve quality, reduce costs, and improve flexibility. You can even launch the resources manually if you wish to.
You can view the CFT with the following link:
NOTE: If you’re launching resources with the above template, make sure you use your AMI ID, roles, and other mappings.
As you can see the stack has been launched successfully and all the resources are ready.
Step 7: CodeDeploy
To begin with CodeDeploy, firstly create 2 roles.
CodeDeploy Role: Default CodeDeploy permissions.
Role for EC2: Attach AWSCodeDeployFullAccess or EC2RoleForCodeDeploy AWS-managed policy to the role.
Now, attach this role to the EC2 instance that is launched previously.
CodeDeploy uses a YAML file which by default is named appspec.yml and found on source code root.
File reference here.
version: 0.0
os: linux
files:
- source: /
destination: /home/ec2-user/server
permissions:
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
hooks:
BeforeInstall:
- location: /deploy_scripts/install.sh
timeout: 300
runas: root
ApplicationStart:
- location: /deploy_scripts/run.sh
timeout: 120
runas: root
The appspec.yml uses shell scripts that handle the hooks. You can access these scripts here.
Now, go to the CodeDeploy service and create an application by providing the application name.
After the application is created we now create the deployment group. Specify a name for the deployment group.
Now, select a role that we created with the code to deploy permissions to grant AWS CodeDeploy to access your target instances.
Selecting deployment type:
In Place: The application goes offline for a few seconds when modifications are made.
Blue/Green (preferred): A new instance will be launched with modifications, by that time the old instances will keep serving users. Here the updates are made with no downtime.
The application we are launching is not that critical and can bear a little downtime of a few seconds so we will be going with the In-Place deployment type.
In the deployment settings, keep the other configurations as default. Now create the deployment group.
Now moving ahead by clicking on create deployment, keep all the settings as it is, and just go for the revision type as shown below.
NOTE: Copy the URI of the artifact stored in S3 and use it as the revision location.
Now we are good to go. Start the deployment.Success! My application is deployed on the EC2 instance, scaled by an Auto Scaling group. You can access the application by ALB DNS.
Step 8: CodePipeline
Now go to the CodePipeline in the AWS console and click on Create Pipeline.
Create a pipeline by mentioning the CodeCommit repository, CodeBuild project, and CodeDeploy application.
After all the stages succeeded, visit the endpoint URL. Your web application should be live now.
- Check your application by IP of our instance :
- Check your application on DNS of load balancer:
Congratulations! You have achieved the seamless Ultimate AWS CICD pipeline🔥.
. . .
Conclusion:
In this article, we explored the process of setting up and optimizing a CI/CD pipeline for a NodeJS application using AWS and CloudFormation. By automating the build, test, and deployment stages, we achieved a more efficient, reliable, and scalable deployment process. This not only reduces the potential for human error but also ensures a consistent approach to software delivery.
Thank you for reading! I hope this guide helps you in your journey to mastering CI/CD with AWS and CloudFormation. If you have any questions or feedback, feel free to leave a comment below.
Happy deploying 🥳!