# CFH CI/CD with CodeCommit, CodeBuild, CodePipeline introduction + Lab
## Lab 1. Basic Scenario - Version Control & Continuous Integration(CI)
### Getting started to turn on your AWS EC2 instance
* Create an AWS EC2 with cfh-demo-ec2
* 
* 
* Set the permission for your AWS EC2 with IAM
* Got to IAM, and create an AWS Role cfh-demo and append to EC2
* Create a Role
* 
* 
* Add “AmazonSSMManagedInstanceCore”(for the web console login use)and “AmazonEC2ContainerRegistryReadOnly“(for the AWS ECR pull container image use)
* 
* 
* Name is cfh-demo
* 
* 
* Result
* 
* Go to your AWS EC2 and modify the IAM Role with cfh-demo
* 
* 
### Getting started with AWS CodeCommit
* Go to AWS CodeCommit and create a repository
* Create a repository cfh_demo_repo with AWS Console UI of AWS CodeCommit
* 
* 
* Go to your AWS Cloud9
* Initialize your repository in your command line
```
git clone {AWS CodeCommit URL}`
```
ex:
```
git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/cfh_demo_repo`
```
* Push your repository to AWS CodeCommit
* Install python3
```
yum install python3 -y
python3 --version
```
* Install the django with version 2
```
pip3 install django==2
python3 -m django --version
```
* Initiate the basic project
```
python3 -m django startproject mysite
```
* Copy file to cfh_demo_repo folder to initial commit and push
```
cp -R mysite/* /home/ec2-user/environment/cfh_demo_repo
```
* Go to the folder
```
cd /home/ec2-user/environment/cfh_demo_repo
```
* Basic configure
```
pip3 install django==2
python3 manage.py migrate
```
* Allow all hosts with
```
sed -i 's/ALLOWED_HOSTS = \[\]/ALLOWED_HOSTS = \[\"*\"\]/g' mysite/settings.py > settings.py
```
* Commit your code and push to the server
```
git add .
git commit -m "Initiate" && git push
```
### Getting Started with AWS CodeBuild
* In your AWS Cloud9, write a simple Unit Test for Continuous Integration (CI)
* Go to the repository folder and create some unit test case
```
cd /home/ec2-user/environment/cfh_demo_repo
mkdir tests
cp mysite/__init__.py tests/
touch test_demo.py
```
* Start to write/add a test (tests/test_demo.py) and remember to Save this modification
* 
* You can copy the code as below ⬇️:
```
from unittest import TestCase
class YourTestClass(TestCase):
def test_something_that_will_pass(self):
self.assertFalse(False)
# def test_something_that_will_fail(self):
# self.assertTrue(False)
```
* Remember to push to your repository
```
cd /home/ec2-user/environment/cfh_demo_repo
git add .
git commit -m "Add the unit test"
git push
```
* Set up your buildspec.yml - it can let AWS CodeCommit run the test for you!
* Create a file buildspec.yml
* 
* Copy codes as below
```
version: 0.2
phases:
pre_build:
commands:
- pip3 install django==2
build:
commands:
# Start to run your unit test
- python3 manage.py test
artifacts:
files:
- "**/*"
```
* Save this file as buildspec.yml and choose the right path cfh_demo_repo
* 
* And you will see this screen
* 
* Remember to push to your repository
```
cd /home/ec2-user/environment/cfh_demo_repo
git add .
git commit -m "Add buildspec.yml for the AWS CodeBuild"
git push
```
* Go to AWS CodeBuild to build up your AWS CodeBuild
* Enter your Project name cfh-demo-master
* 
* Set the Source & Branch
* 
* 
* Set your Environment
* 
* 
* Set your Logs for monitoring
* 
* Trigger your CI(Continuous Integration)
* Click the Start build to test
* 
* You can check the Build logs & Phase details
* 
* 
### Getting Started with AWS CodePipeline
* Go to AWS CodePipeline and create your master(main) pipeline cfh-demo-master
* 
* 
* 
* 
* 
* Click Next
* Waiting for about 1 minute
* 
* Start to test your automation Continuous Integration(CI)
* Go to AWS Cloud9 and update your code to trigger the AWS CodePipeline
* Update test_demo.py
```
from unittest import TestCase
class YourTestClass(TestCase):
def test_something_that_will_pass(self):
# Add a new line for testing the AWS CodePipelin & Continuous Integration(CI)
print("This is just a test")
self.assertFalse(False)
# def test_something_that_will_fail(self):
# self.assertTrue(False)
```
* And git push it
* 
```
cd /home/ec2-user/environment/cfh_demo_repo
git add .
git commit -m "Testing the AWS CodePipelin & Continuous Integration(CI)"
git push
```
* Check your AWS CodePipeline
* 
* Congratulations! 🎉 Your basic Continuous Integration(CI) completed!
---
## Lab 2. Advanced Scenario - Continuous Delivery & Continuous Deployment(CD)
### Set up your EC2 environment for the deployment
* Connect your EC2 instance
* 
* 
* 
* Set up your docker
* Install docker
```
sudo yum install docker -y
```
* Start docker
```
sudo systemctl start docker
```
* Allow Session Manager can execute docker
```
sudo setfacl --modify user:ssm-user:rw /var/run/docker.sock
```
### Set up AWS CodeBuild of CI(Continuous Integration) for the AWS Elastic Container Registry(ECR)
* Create a repository in the AWS AWS Elastic Container Registry(ECR)
* Go to AWS ECR(Elastic Container Registry) and create a repository cfh-demo-master
* 
* 
* 
* Click it to get more information for pushing docker images
* 
* 
* 
* Go to AWS Cloud9 and create a Dockerfile to build the Docker image
* Create a Dockerfile
* 
* You can copy & paste following the below
```
FROM python:3.7.16
USER root
WORKDIR /usr/src
ENV TZ Asia/Taipei
RUN pip3 install django==2
COPY . /usr/src
ENTRYPOINT ["python3","manage.py","runserver","0.0.0.0:8080"]
```
* 
* Save it as Dockerfile
* 
* 
* Go to IAM Role to add AmazonEC2ContainerRegistryFullAccess and AmazonElasticContainerRegistryPublicFullAccess to your AWS CodeBuild role (codebuild-cfh-demo-master-service-role)
* 
* You can search with the keyword “containerregistry”
* 
* Modify your buildspec.yml with the AWS ECR sample commands
* 
* Go to AWS Cloud9 to adjust the buildspec.yml
* 
* And git push to AWS CodeCommit
```
git add . && git commit -m "Add Dockerfile and add AWS ECR commands to buildspec.yml" && git push
```
### Set up your CD(Continuous Delivery) AWS CodeBuild
* Add the specific deployspec.yml with AWS Cloud9
* 
* After click New File, please MODIFY {parameters} below codes and paste on the new file
```
version: 0.2
phases:
build:
commands:
# Start to run your unit test
- aws ssm send-command
--document-name "AWS-RunShellScript"
--targets '[{"Key":"InstanceIds","Values":["{YOUR EC2 INSTANCEID}"]}]'
--parameters '{"commands":[
"sudo su",
"systemctl start docker",
"docker rm -f cfh-demo",
"{YOUR ECR LOGIN COMMAND}",
"docker pull {YOUR ECR URL with TAG}",
"docker run -d --name cfh-demo -p 80:8080 {YOUR ECR URL with TAG}"]}'
artifacts:
files:
- "**/*"
```
* Sample code(please don’t directly copy, remember to modify the parameter)
```
version: 0.2
phases:
build:
commands:
# Start to run your unit test
- aws ssm send-command
--document-name "AWS-RunShellScript"
--targets '[{"Key":"InstanceIds","Values":["i-0d48c3c55c19ec5f0"]}]'
--parameters '{"commands":[
"sudo su",
"systemctl start docker",
"docker rm -f cfh-demo",
"aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 915311728802.dkr.ecr.us-west-2.amazonaws.com",
"docker pull 915311728802.dkr.ecr.us-west-2.amazonaws.com/cfh-demo-master:latest",
"docker run -d --name cfh-demo -p 80:8080 915311728802.dkr.ecr.us-west-2.amazonaws.com/cfh-demo-master:latest"]}'
artifacts:
files:
- "**/*"
```
* 
* And the save it with the name “deployspec.yml”, please do remember to chose the right path with your project “cfh_demo_repo”
* 
* 
* 
* And then git add, git commit, and git push to the master branch
```
git add . && git commit -m "Add the deployspec.yml" && git push
```
* Go to AWS CodeBuild and start to create a AWS CodeBuild with cfh-demo-master-deploy for the deployment process
* 
* 
* 
* 
* Enter deployspec.yml
* 
* 
* Go to IAM Role to add a permission “AmazonSSMAutomationRole” for this role “codebuild-cfh-demo-master-deploy-service-role”
* 
* 
* 
* Go to your master AWS CodePipeline to add AWS CodeBuild for the deployment process
* Click Edit
* 
* Click Add stage
* 
* Enter the stage name Deploy
* 
* Click Add action group
* 
* Enter the information as below and click Done
* 
* Click Done
* 
* Click Save
* 
### Test your CI / CD pipeline
* Click Release change to test it
* 
### Insert a manual approve process
* Click Add stage under the Build Stage
* 
* Enter the name Approval and click Add stage
* 
* Click Add action group
* 
* Enter the information as below and click Done
* 
* Remember to click Save
* 
### Test your complete process
* Click Release change
* 
* When the pipeline goes to this process Approval, it will need to click the Review to get the approval.
* 
* You need to click the Approval to let the process keeps going
* 
* 
* Congratulations! 🎉 Your have completed an excellent CI(Continuous Integration) & CD (Continuous Delivery) pipeline
---
## Lab 3. Extra Scenario - PR(Pull Request) with develop & master(main) pipeline
### Create a develop branch
* Go to AWS Cloud9 and create a branch develop
```
cd /home/ec2-user/environment/cfh_demo_repo
git checkout develop
```
* Push develop branch to AWS CodeCommit
```
git push --set-upstream origin develop
```
### Set up AWS CodeBuild & AWS CodePipeline for your develop branch
You can follow the master branch’s building process
* Create the AWS CodeBuild for develop with cfh-demo-develop
* 
* 
* 
* 
* 
* Create the AWS CodePipeline for develop with cfh-demo-develop
* 
* 
* 
### Set up the approval setting of master branch PR(Pull Request)
* 
* 
* 
* Go to AWS Cloud9 and the commit and push a new update for testing the PR
* 
```
git add .
git commit -m "Add a unit test for PR test"
git push
```
* 
* Check your AWS CodePipeline
* 
* Create your PR from develop branch to master branch
* Go to your Repository and click to enter it
* 
* Click the Create pull request
* 
* Click Compare and select the develop branch as the Source and select the master branch as the Destination
* 
* Enter the Title of PR
* 
* Then you can see the differences as below and click Create pull request button
* 
* And you will set the result as below
* 
* How to merge the PR?
* You need another user(colleague) to press the approval button - This is the correct and normal process
* You can use Overwrite approval rules - This is the special case and unusual process
* 
* 
* After clicking the Merge button you will see the UI as below
* 
* For this case, do NOT check the option, it will delete your develop branch
* 
* After checking and choose the Merge strategy, please click Merge pull request, and go to AWS CodePipeline to check the master’s pipeline
* 
Congratulations! 🎉 You have learned how to create a PR!