In this tutorial, I will show you how to set up a simple CI/CD pipeline that compiles code on GitLab and then deploys to
AWS EC2 via
AWS CodeDeploy. This tutorial assumes:
- You have a working
EC2 Ubuntuinstance set up with a web server such as
Apacherunning and configured.
- You have an existing code repository hosting an
Angularproject on GitLab.
- Angular 7
- Gitlab CI/CD
- AWS S3
- AWS CodeDeploy
- AWS EC2 Ubuntu 18.04 LTS
I’ve made a start project that I will be referencing throughout this project on Github will all the files you need already built in. Check it out here!
Step 1 – Create an S3 to AWS CodeDeploy Pipeline
I really don’t like dropping links in tutorials like this, however, for the sake of not re-writing Amazon’s documentation, I will have to tell you to follow all instructions in the tutorial in the link below. Only once you finished the tutorial will you be able to continue with the rest of this tutorial. Once you’re done with Amazon’s tutorial, you will have a CD pipeline ready to go waiting for GitLab to send the code.
If you have successfully completed the above tutorial, any changes pushed to your S3 bucket will be deployed immediately to your EC2 instance. Then steps below will show you how to upload your production bundle to S3 from Gitlab to complete the CI/CD pipeline.
Step 2 – Create an appspec.yml
Welcome back! The first thing we’ll have to do is create an
appspec.yml file in the
src/ folder of our project. The
appspec.yml will tell AWS CodeDeploy to deploy your code in a specific file directory on the server – in our case, it’s the
version: 0.0 os: linux files: - source: ./ destination: /var/www/
Then we have to tell angular to include this file as an asset so it stays preserved during the production build. To do this, we edit the
assets block in our
angular.json file to include
... "tsConfig": "src/tsconfig.app.json", "assets": [ "src/favicon.ico", "src/assets", "src/manifest.json", "src/appspec.yml" ], "styles": [ ...
Step 3 – Create .gitlab-ci.yml
Gitlab offers a continuous integration service if you add a
file to the root directory fo your code repository. I’ve provided a sample
.gitlab-ci.yml file as seen in example Github project. Please be sure to update the group name and repository name for your own project. If you copy this code please be sure to use your own repository name.
image: node:10 stages: - build - deploy build: stage: 'build' script: - apt update - apt-get install -y nodejs - npm install -y firstname.lastname@example.org - nodejs -v - npm -v - ls -la -F - npm ci - npx ng build --prod cache: paths: - node_modules/ artifacts: when: on_success name: '$CI_JOB_NAME-$CI_COMMIT_REF_NAME' paths: - dist/angular-gitlab-ci-cd-example/ only: - dev - master deploy: stage: 'deploy' environment: name: production script: - apt update - apt install -y software-properties-common - apt install -y python-dev - apt install -y python-pip - pip install awscli - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - aws configure set region us-east-1 - ls -la -F - mv dist/angular-gitlab-ci-cd-example/appspec.yml dist/ - cd dist - ls -al -F - cd .. - aws deploy push --application-name angular-gitlab-ci-cd-example --s3-location $AWS_S3_LOCATION --ignore-hidden-files --source dist only: - master
If you commit to your master branch with this file in the root directory of your project, a CI pipeline will initiate with two steps outlined line-by-line below:
The Build Stage
1.Update the packages in the
- apt update
- apt-get install -y nodejs - npm install -y email@example.com - nodejs -v - npm -v
- npm install
4. Build the production bundle of Angular using the local cli
- npx ng build --prod
6. Tell GitLab to cache your
node_modules so that your project builds faster next time around
cache: paths: - node_modules/
7. This code block creates a
build artifact that will be passed onto the next stage in the pipeline if all operations in the container run without error. In the case of
Angular7, I’m passing the created
dist/ directory to the next stage so that GitLab can send it to AWS to be deployed
artifacts: when: on_success name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME" paths: - dist/angular-gitlab-ci-cd-example/
8. This keyword tells GitLab only to run this stage when a commit is pushed to either the master and dev branches. You can customize any stage to run a specific set of branched or all branches if that’s what you need.
only: - dev - master
The Deploy Stage
1. Update the packages on the
Docker image, install the python libraries needed for
AWS CLI and then install the
script: - apt update - apt install -y software-properties-common - apt install -y python-dev - apt install -y python-pip - pip install awscli
2. Navigate to your CI/CD settings in GitLab and add the following variables for your
$AWS_SECRET_ACCESS_KEY from the
CodeDeploy IAM User you created earlier from following the
AWS tutorial in Step 1. You should also include the
$AWS_S3_LOCATION as a CI/CD variable as well in the following format:
<key> will be by the same name as the zip created from the build stage.
3. In this step, we are configuring the
AWS CLI with the
IAM Credentials of a user with the correct CodePipeline policies attached.
- aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - aws configure set region us-east-1
4. Remember from step 1 how we made sure the appspec.yml was preserved in the
dist/ production bundle? Well, now we have to move it out it to the same directory level as the
dist/ folder so that it sits on the same level as the
dist/ folder. We have to do this to make the
appspec.yml visible to
AWS. If we do not do this, the
AWS CLI will throw an error stating that it cannot find the
appspec.yml file in the next step.
- mv dist/angular-gitlab-ci-cd-example/appspec.yml dist/ - cd dist - cd ..
5. Use the
AWS CLI to deploy the
dist/ bundle to
- aws deploy push --application-name angular-gitlab-ci-cd-example --s3-location $AWS_S3_LOCATION --ignore-hidden-files --source dist only: - master
Once you push your code to the master branch, navigate to the CI/CD pipeline and watch your code being built. Once GitLab is done building the production bundle, it will send it to
AWS S3, which in turn will be deployed onto your live server moments later. I would love to hear your feedback on how I can improve this simple pipeline.