CI/CD: Increase your Development Pace

Jonathanjojo
4 min readApr 26, 2020

--

To automate and ultimately speed up your deployment chores, once and for all

Source: https://medium.com/@nima.2004hkh/ci-cd-and-dockerize-a-react-project-b389f9735a5e

This article is written as a part of individual review criterion of PPL CS UI 2020

Overview

I assume by the time you read this blog, you know that an app cannot be sitting on your computer and running locally only. Most of them need to be published so others can use it.

And if you are aware of that, you must know that publishing or deploying an application is one hell of a chore to do, especially when you have to do it over and over every time you update the application.

Sit back and relax, with some easy steps you can be just like me and my team, where we do not worry about the hustle of deployment anymore. Now let's dive into CI/CD.

Continuous Integration (CI)

Simple to say, CI is the name given to the processes of preparing the code to be released. These processes include:

  • Building the app
  • Running tests
  • Report and distribute the results

Continuous Delivery (CD)

Meanwhile, CD includes some processes that execute the deployment/release process. Basically, this process is the one moving your code from your repository to the server in which the application resides and running.

How we do it on our team at PPL

I am developing the backend server for our project. And we decided to have our application to be served on Heroku. Since we have two environments: one for developments (staging) and another one for the real deal (production). Therefore:

1. Created two Heroku apps and their associated database

We created 2 Heroku apps, and we added a Postgres Add-On to each of them. Go to their dashboard and you can achieve this with some simple clicks. Psst, it’s free :)

Say you have 2 apps called app and app-staging , then your apps will be accessible through :

  • app.herokuapp.com
  • app-staging.herokuapp.com

2. Create the application

We use Django-REST as our application framework. We find it easy to work with, flexible, and we are already quite familiar with some of its features. So we created one (just one)

3. Create a git repo for the application

We are provided with a GitLab enterprise account, so we push our application to this repo. For the two environments, we have 2 branches to differentiate them: master and staging .

4. Setup CI/CD files

Since we are using Gitlab and it’s registered pipeline which is Gitlab-CI, we provide it with a .gitlab-ci.yml as a configurational script for our CI.

This file will instruct the Gitlab Runner to executes some commands. Moreover, we can divide them into stages like test , deploy , etc. In our case, we have code analytic tools called SonarQube, which we also plugged in here.

stages:
- test
- sonar-scanner
- deploy

test:
image: python:3.6.5
stage: test
before_script:
- pip install -r requirements.txt
- python manage.py makemigrations
- python manage.py migrate
- python manage.py collectstatic --no-input
- python manage.py runserver 8000 &
when: on_success
script:
- echo "Starting linter"
- sh lint.sh
- echo "Starting tests"
- coverage erase
- coverage run --include="./*/*" --omit="./env/*","./project/*","./manage.py" manage.py test apps
- coverage xml -i
- coverage report -m
artifacts:
paths:
- coverage.xml

SonarScanner:
image:
name: sonarsource/sonar-scanner-cli:latest
entrypoint: [""]
stage: sonar-scanner
script:
- sonar-scanner
-Dsonar.host.url=$SONARQUBE_URL
-Dsonar.login=$SONARQUBE_TOKEN
-Dsonar.branch.name=$CI_COMMIT_REF_NAME
-Dsonar.projectKey=$SONARQUBE_PROJECT_KEY

deploy:
image: ruby:2.4
stage: deploy
before_script:
- gem install dpl
- wget -qO- https://cli-assets.heroku.com/install-ubuntu.sh | sh
- >
if [[ "${CI_COMMIT_REF_NAME}" == "staging" ]];
then
export HEROKU_APP_NAME=$HEROKU_STAGING_APP
HEROKU_APP_HOST=http://tuberculosis-ppti-staging.herokuapp.com/
ENVIRONMENT_NAME=staging
DATABASE_URL=$DATABASE_URL_STAGING
export DATABASE_NAME=$DATABASE_NAME_STAGING
export DATABASE_USER=$DATABASE_USER_STAGING
export DATABASE_PASSWORD=$DATABASE_PASSWORD_STAGING
export DATABASE_HOST=$DATABASE_HOST_STAGING
elif [[ "${CI_COMMIT_REF_NAME}" == "master" ]];
then
export HEROKU_APP_NAME=$HEROKU_PRODUCTION_APP
HEROKU_APP_HOST=http://tuberculosis-ppti.herokuapp.com/
ENVIRONMENT_NAME=production
DATABASE_URL=$DATABASE_URL_PRODUCTION
export DATABASE_NAME=$DATABASE_NAME_PROD
export DATABASE_USER=$DATABASE_USER_PROD
export DATABASE_PASSWORD=$DATABASE_PASSWORD_PROD
export DATABASE_HOST=$DATABASE_HOST_PROD
fi
- export DATABASE_PORT=5432
- export DATABASE_IS_PSQL=true
script:
- dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_API_KEY
- export HEROKU_API_KEY=$HEROKU_API_KEY
only:
- staging
- master
environment:
name: $ENVIRONMENT_NAME
url: $HEROKU_APP_HOST

You can see our customization on the production and staging is set on the conditionals on the

if [[ “${CI_COMMIT_REF_NAME}” == “staging” ]];
...
elif [[ "${CI_COMMIT_REF_NAME}" == "master" ]];
...
fi

There you have it. As you can see, there are some variables noted in $VARIABLE . You can set their value in secret through the settings. Why? So it does not available in public, of course, it is a secret anyway.

Environment variables. Make sure you have the authority to set these up.

Now, since we intend to deploy our apps to Heroku, it demands us to have Procfile to set up the webserver that is going to run our application. The contents of this file Procfile can be as simple as :

web: gunicorn app.wsgi

Where your app name should substitute the above app.

5. Push code to this repo = deploy

Just push it with git push [remote-name] [branch] (now your branch has to be either staging or master as we described in the script), and it will deploy your code to the corresponding application!

Jobs created

References

--

--

No responses yet