CI/CD – Continuous Integration & Continuous Deployment

(An implementation of Dev/Prod Parity Factor)

Introduction


One of the factors of a cloud native application is ‘Dev/Prod Parity’ defined as there should be minimum parity between the application in Development and Production environments.

This can be achieved by implementing CI/CD – Continuous Integration & Continuous Deployment. This article introduces the concept of CI/CD. To leverage the features of the cloud applications need be cloud native applications. A cloud native application is defined below:

A Cloud Native Application is an application that was developed with the cloud principles of: robustness, scalability, easy integration, portability, and administration into its design.

In order to design a cloud native application one needs to adhere to the 12 factors (and more) to utilize cloud features effectively.

One of the twelve factors is that the release versions between what is in the code repository and production should be minimal; and this can be accomplished by multiple releases in small time frame, with small increments in code base.

In this article we introduce Dev/Prod parity and summarize its’ importance in a cloud native application.

Dev is prod meme

Sad but true that in certain places folks actually implemented this method and the application is down while the developer pushes in the latest changes.

Background

Hello John, this is Rajeev. I have finished coding and it has been reviewed. I pushed the code to CVS, can you please deploy it to test environment when you get a chance? LMK when it is complete.”

“Sure, however, I can do it tomorrow morning. Hope that is OK. Any special instructions to deploy this release to test environment?” said John on the phone, at 4 pm on Wednesday.

“Morning is fine. Nothing special. Thanks”

The above is a typical conversation I have had (or email exchange) with Config and Security team (now known as DevOps) back in 2000s and before.

The method followed had many manual steps and communication was essential between developers, project managers, config team, testing team, users and product owner. This is shown in the figure below:

2000s build, deploy applications
Before CI/CD Pipeline, a case of how apps were built and deployed.

In this company the following were the steps :

  1. Developers coded new functionality or fixed bugs and unit tested the code on their local machines. They also build the archive file of the application and deployed to dev environment. Did a manual  integration test and pushed the code to code repository and communicated to the config (now known as DevOps team) to deploy to test environment.
  2. DevOps then would use the config file for test environment (server) and manually build the application archive with the latest code from the repository; deploy the archive to the test environment and communicated to QA to test the application.
  3. QA would test in the application and then assuming everything went well would communicate to product and project manager that the release of the application is good to go into higher environments.
  4. DevOps would build using a staging env configuration file and deploy to staging environment. In this environment the users would test the application and verity they got what they requested.
    If everything was good then, devOps would deploy the staging application archive (assuming the production uses the same config file as staging) to production server.

Pain Points

Some of the pain points in this method:

  • Unit tests were minimal as it could be bypassed. TDD was not practiced.
  • Integration tests were non existent or mostly manual.
  • No visibility for non-devs on unit tests and integration tests success or failure.
  • Configuration files for each environment was part of the application. Special care must be taken to build the application with the correct config file for the deployment enviornmnet. 
  • manual steps translate to human error; very little automation. Risks not meeting the deadline.

Continuous Integration/Continuous Deployment

A quick view of CI/CD is shown :

which shows all the steps and also very few manual interactions. Now let us get into the definitions and terminology of the components that make up a CI/CD pipeline.

Terminology

Continuous Integration is integrating code from repository and running tests to check if everything OK.

Continuous Delivery gives us the app archive file for deployment to production (manually). 

Continuous Deployment  is pushing it to production automatically.  

A good reference which explains in more detail is here.

To implement a successful, seamless CI/CD, it is important that every team in the company follows best practices, then one can have an effective automated CI/CD. The difference between continuous delivery and continuous deployment is shown below

Difference between Continuous Delivery & Deployment

Unit Testing

Developers need to write unit tests for each functionality the code. This should include:

Unit test for each method in the class.
Every use case should be covered for the function including boundary values and exceptional cases.
Use mocking libraries to achieve dependencies.
Developers should check their code into the repository only if all unit tests pass (not just theirs).


Integration Testing

Integration tests are tests which check how your code integrates with the other functionalities of the code. This is not an easy thing to code; however, it needs to be done. A good resource on the differences of unit testing and integration testing is here.

It can be achieved by using embedded or in memory databases, mocking external APIs by using mocking libraries.

Unit and Integration testing are automated in CICD whenever a developer checks in his code into the code repository. If there is any failure then the automation stops until another push is made into the code repository.

Build Application

In the ‘Background’ section, we saw that the builds were happening on local machines. This is poor, as 9/10 times there will be some dependencies which are missing in the build file.

Having the build happen outside of the local individual eliminates unnecessary issues.

For each environment, developers would store configuration files inside the applciation code base. These files need to included when the application is being built in conjunction with the environment the archive is being made.

One of the factors in the twelve factors is Config files should be stored external to the application. This de-couples the environment variables from the application, and gains security as only DevOps will know the secrets and can change them without depending on the developers to change the code.


Deliver Application


Delivering the application means delivering the archived file to a location where it can be retrieved and then deployed. Another possibility is creating the archive application file in the environment.

In the ‘Background’ section, we observed that for each environment the application had to be delivered to the environment manually, which can lead to errors.

Deploying Application


In each environment, the application archive file is available and ready to be deployed. Deployment in a seamless CI/CD pipeline is generally automatic. Some methods used in deployment are canary deployment, blue/green method, and feature deployment.

So CI/CD is automating the steps we saw in ‘Background’ section, so that there is minimal manual interaction. Here is my favorite way of depicting the CI/CD pipeline which I am sharing from Jyothi Sahu’s article.

Some key things to observe in CI/CD pipeline is that all unit tests, integration tests are triggered post commit by the developer. The DevOps team has option to do either manual deployment or automatic deployment.

There are many other topics which one can go into great details – best practices for unit tests and integration tests using Test Driven Design (TDD), Behaviour Driven Design (BDD); tools to use in development of these tests; deployment methodologies – canary or blue/green or manual to production env and storage of secrets so that they are picked up during deployment or execution time.

All of these topics are for another time. The goal here was to introduce CI/CD and its’ importance in cloud native application.

Summary

All of these together make up Continuous Integration and Continuous Deployment pipeline which is depicted below:

In this article, we looked into one of the important factors of a cloud native application – development/production environment parity. To implement this factor, we implement continuous integration testing and continuous deployment.

In implementing CI/CD we also implemented other factors of the twelve factors of cloud native applications, specifically:

  1. One code base for all environments.
  2. Dependencies – explicitly declare and isolate dependencies. Not building on local machines and then deploying.
  3. Configuration files stored in the environment.
  4. Build, release, run – separate build and execute stages.
  5. Disposability – maximize robustness with fast startup and graceful shutdown and
  6. Dev/Prod Parity – keep development, staging, and production as similar as possible

For further reading and details refer the links below in references.


References

  • https://12factor.net/ – the original 12 factors for cloud native applications.
  • https://testrigor.com/blog/what-is-cicd/ gives some detailed definition of CI/CD terminology with good pictures.
  • https://www.baeldung.com/cs/unit-vs-integration-testing – differences between unit and integration testing.
  • https://www.opsmx.com/blog/what-is-a-ci-cd-pipeline/ – a good article with the image being referenced in this article.
  • https://katalon.com/resources-center/blog/ci-cd-pipeline – the featured image for this article is sourced from this link.

Leave a comment

Your email address will not be published. Required fields are marked *

5 thoughts on “CI/CD – Continuous Integration & Continuous Deployment”