In a custom software development company it is crucial that the effort of the professional developers is focused on delivering value. This is achieved through maximizing the time spent on executing the work that they are most proficient at doing. The delivered value for example could be a newly added functionality or improved existing functionality.
This may sound pretty attractive – maximizing the time that you spend, doing the things that you are most proficient at, providing the maximum value that you could generate.
So, how do we maximize the time we spend on things that bring the most value?
What is Continuous Integration (CI)?
Continuous integration (CI) is the automated process of integrating newly added code by a software developer to a common codebase.
“Continuous” entails that this is a process that each and every developer of the team is doing repetitively and often. Eventually, it’s done multiple times a day within the same team/codebase. As part of the process, it is expected that the newly introduced changes are validated and tested through automated builds so that they don’t break existing functionality.
The processes/builds that are repetitively executed in an automated way are often implemented and referred to as pipelines.
Goals of CI
- automating the tedious repetitive manual labor
- enabling developers to focus on development
- accelerating delivery of new features
- frequent integration cycles / small Pull Requests (PRs)
- improving the quality of delivered features
- improving the quality of an existing codebase
- catching errors earlier
- lowering cost of errors and bugs
- preventing integration hell
What is Continuous Delivery (CD)?
Continuous delivery (CD) is the automated process of delivering the increments of our codebase to the desired environment.
CI continuously delivers the newly implemented functionalities to different user groups – developers, testers, product owners, end users. It makes the functionalities available for use. CD is the next step in the software delivery process after CI.
There could be different environments that CD is delivering to:
- staging / demo / acceptance
The continuous delivery process could be either a manually triggered or an automatically triggered one, depending on what the business desires. For example we could want an automatic CD pipeline to be run when we have successfully finished the execution of our CI pipeline and our fresh code increment was just merged to the common codebase. Such CD pipelines often deliver the latest state of our codebase to environments that are not being used by our end-users. In the case of delivering to a production environment, the business often prefers that this step is triggered manually.
In the case where we have an automatic deployment of software that passed successfully CI the process is called continuous deployment (not to be confused with continuous delivery).
What is the Difference?
So, to recap what we have so far:
- Continuous integration (CI) takes care of of integrating and validating the quality of the newly introduced code by developers to the common codebase in an automated way
- Continuous delivery (CD) takes care of delivering a specific version (usually the latest) of our codebase to a specific environment in an automated way, making it available for a specific user group
- Continuous deployment takes continuous delivery on steroids, the process is no longer only done in an automated way, it is being triggered and executed automatically
The CI and CD processes are responsible for different parts of the software development delivery process. One affects existing codebase, the other affects existing environments.
Why do we use CI and what are the Benefits?
In its core, CI is making manual labor an automatic one. Validating the quality of what we introduced, delivering the desired functional requirements to the system that is developed.
Having a process that is being followed for achieving said purpose allows us to deliver successfully and meet certain expectations and requirements each and every time. Most processes have this purpose – repetitively delivering successful results with a specified quality. Making this process an automated one is crucial. We are transferring effort from repetitive manual labor to some other area like achieving accelerated software development and delivering more features with higher quality more frequently. It allows us to focus on what is important – on the core of our everyday work as software developers – producing and improving existing software. Sounds like a competitive advantage, doesn’t it?
One important goal which is addressed during the CI process is preserving the existing functionality in the way it is expected to work. It is expected that the produced software gets better with time and not deteriorating. One way to achieve this is through writing different kinds of tests, which validate certain aspects of the software and its behavior. This is especially true for the critical functionalities of the system. Here you should also get familiar with the testing pyramid. I will just hint that it goes like this: Unit tests -> Integration tests -> End to end (E2E) tests. While the greatest value is most probably on the tests on the right, they also take the longest to execute.
We shall not only write tests, but also execute them and make them part of the CI process. Please, keep in mind that tests do not prove the absence of bugs. They only increase our confidence in the software that we are producing. We are also reducing the risk that each integrated piece of software brings with itself. We are receiving frequent feedback allowing for less errors and a reduced cost of bugs. The cost of a bug increases with each next step in the software process. It is cheapest when bugs are found early during development (e.g. through unit tests). They are most expensive and could be directly affecting our reputation, performance and even cash flow at the moment they are discovered by an end user in production.
CI, when done properly, also increases the transparency of the progress and the current state of development. It gives us answers to the questions “What is happening?” and “Do we need to do something next?”.
CI empowers us to produce software in a sustainable way. It enables us to create a consistent pace to follow.
Best Practices in CI
Let’s get practical here. Here are a few tools that are state of the art and you can get your hands on:
Some best practices from real life experience:
- Write tests for all mission-critical functionalities, functional and non-functional qualities that you want your system to comply to.
- Run all available tests on each integration build.
- Having more and better written tests will lower the time that you spend on debugging.
- Write a failing test, add just enough production code for the test to pass, refactor the production and test code, repeat.
- This is also known as Test driven development (TDD)
- Become aware of the testing pyramid and the value and impact that the tests on each layer have.
- Do not disregard manual and exploratory testing.
- Have people that take care specifically for that part of the software development process like SysAdmins or DevOps.
- Enable developers to focus on what they are good at writing code and producing features for the product.
- Enforce static analysis on the code, e.g. with SonarQube and SonarGraph so that the quality of the code can become transparent in order for it to be observed in time.
- It is a good idea that there is a quality gate enforced on each Pull Request (PR) as part of the CI process that will not allow code with low quality to get integrated into the common codebase.
- This is also a way that technical debt can be kept under control.
- Enable developers to test the code-to-be-integrated into the common codebase as easily and as quickly as possible. Literally this means being able to create an environment from the code version of a particular pull request. These are known as preview environments or feature environments.
You can also read more about the Ten Commandments Of GitOps Applied To Continuous Delivery
Do you want to continuously integrate our hands-on software development experience in order to boost your business success?