Change/update your production webapp features with a push to GitHub using Codedeploy

Ishak M. B (Isaak)
5 min readDec 7, 2022

--

Last year I used CodeDeploy to launch an app on AWS and built a CI/CD pipeline, whenever I needed to change something on my backend I only make the necessary changes and just push the code to GitHub.

This article is made for anyone who needed to automate his work as a developer and create a productive work environment and I kinda need to write this down in case I needed to repeat these steps.

You need to have:

S3 bucket for your deployed files

EC2 instance with all the configuration/type and security group..etc

Other things such as database and how you would like your backend and frontend deployed…etc are up to you to decide as long as you have your app running and intact.

The VM I am using has the following configs:

  • Operating system Ubuntu 22.04.1 LTS
  • Instance type: t2.medium, 2vCPU, 4 GiB Memory
  • S3 Bucket
  • Relational Database Service (PostgreSQL)

— — — I am only targetting the backend — — —

First things first, let’s install Codedeploy agent on our virtual machine. When I tried to it I found some difficulties with the AWS documentation, because I am using Ubuntu 22.04.1, I found this solution on Stackoverflow and it worked. (If you have another operating system make sure to do your research about the installation of Codedeploy Agent)
Connect to your VM through SSH and run these commands:

sudo apt-get install ruby-full ruby-webrick wget -y

cd /tmp

wget https://aws-codedeploy-us-east-1.s3.us-east-1.amazonaws.com/releases/codedeploy-agent_1.3.2-1902_all.deb

mkdir codedeploy-agent_1.3.2-1902_ubuntu22

dpkg-deb -R codedeploy-agent_1.3.2-1902_all.deb codedeploy-agent_1.3.2-1902_ubuntu22

sed 's/Depends:.*/Depends:ruby3.0/' -i ./codedeploy-agent_1.3.2-1902_ubuntu22/DEBIAN/control

dpkg-deb -b codedeploy-agent_1.3.2-1902_ubuntu22/

sudo dpkg -i codedeploy-agent_1.3.2-1902_ubuntu22.deb

sudo systemctl list-units --type=service | grep codedeploy

Run the following command to make sure that your Codedeploy Agent is running

#Run the following command to make sure that your codedeploy agent is running
sudo service codedeploy-agent status

You should see this response:

Now let’s create our environment.

  1. Go to Roles > Create role> choose AWS service, Use case EC2, and click Next. Search for AmazonEC2RoleforAWSCodeDeploy in the permissions tab and change the trust policy in the Trust relationships tab so it looks like this:
{
"Version": "2012–10–17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

2. Give the role a let’s say this is role1 and click create role. After creating the role go back to your EC2 instance select your instance > Actions > Security > Modify IAM role search for the role1 you just created and click Update IAM role, with this we just assigned a role to our EC2 instance, which Allows EC2 instances to call AWS services on your behalf.

3. Go back to the Roles tab and let’s Create another role. Follow the same steps above, and this time give it a name role2 when we get to the permission tab search for AWSCodedeployRole this will allow CodeDeploy service access to expand tags and interact with Auto Scaling on your behalf. In the Trust relationships make sure that your trust policy has these lines:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "codedeploy.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

Click create role.

4. Go to CodePipeline and head to the CodeDeploy in the Deploy tag > select Applications > Create application. Give it a name and for the Compute platform choose EC2/On-premises hit create.

5. Under Application Details section select Deployment Group and create a deployment group. Give it a name and search for role2 in the service role> Deployment type: In-place > Environment configuration > check Amazon EC2 instance and choose the key and the value of your EC2 instance (when you create your instance you should give it a name which will be the Value of your key). Leave everything as it is and uncheck the Load Balancer.

6. Go to Pipeline > create pipeline > give it a name (a role name will be created automatically) click next. Choose your source provider, in our case it is GitHub (Version 2), connect to GitHub, choose your repository name, your branch (leave the rest as it is) click next. Skip the Build stage (it is automatic), and choose AWS Codedeploy as your deploy provider, choose the Application name that you have previously created and also the Deployment group and hit next. Click create pipeline (you will automatically attempt you first deploy according to your latest push on github)

At this point our configuration and environment is ready and finished, each time you need to add a feature to your production webapp just make a push to github the linked repo>branch and it will be updated

I have three scripts that manage all this feel free to use them I have gathered them from many sources and made up my own based on my needs

  1. application_start.sh with the script:
#!/bin/bash

#give permission for everything in the express-app directory
sudo chmod -R 777 /directory/appBackend

#navigate into our working directory where we have all our files OR exit
cd /directory/appBackend || exit

#add npm and node to path
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # loads nvm bash_completion (node is in path now)
#install node modules
npm install
npm install pm2@latest -g

#pm2 stop all
pm2 stop appBackend
pm2 start ecosystem.config.js --env prodaws

2. application_stop.sh:

#!/bin/bash
#Stopping existing node servers
echo "Stopping any existing node(PM2) servers"

#it has to be silent
pm2 stop --silent appBackend

3. before_install.sh:

#!/bin/bash

#download node and npm --make sure that the nvm version is the latest--
#there is a script in GitHub that will update the nvm automatically https://github.com/nvm-sh/nvm#install--update-script

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
. ~/.nvm/nvm.sh
#it is better to install --lts version to avoid any disruptions in the future
nvm install --lts
#create our working directory if it doesnt exist
DIR="/directory/appBackend"
if [ -d "$DIR" ]; then
echo "${DIR} exists"
else
echo "Creating ${DIR} directory"
sudo mkdir ${DIR}

4. verify_service.sh:

#!/bin/bash
echo "Testing deployment of service..."
sleep 30 # Waits 30 seconds.

# send a curl request to the backend, and get the response json
result=$(curl -H "Accept: application/json" -s "http://localhost:4000/" | python3 -c "import sys, json; print(json.load(sys.stdin)['state'])")

if [[ "$result" =~ "The app is running" ]]; then
echo "Successful deployment of service"
exit 0
else
echo "Failure deployment of service"
exit 1
fi

Finally, I would like to say that there is so many scenarios that could be achieved through these scripts and Codedeploy I hope this article is helpful, if you find any mistake please point it out so we could make it right, if you have any suggestions please feel free to drop them.

Thank you for reading

--

--

Ishak M. B (Isaak)

Certified IT Support Specialist, Developer, Junior Cyber Security Researcher, I like manipulating code, Tech Volunteer, Interested also in Cloud & Data Analysis