In this blog, Saahas Kulkarni explains what CI is and what Continuous Integration Best Practices will help you get optimal value.
What is Continuous Integration?
Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily – leading to multiple integrations per day.
Each check-in is then verified by an automated build, allowing teams to detect problems early.
By integrating regularly, you can detect errors quickly, and locate them more easily.
What are the benefits of Continuous Integration?
1. Reduce risks
The trouble with deferred integration is that it’s very hard to predict how long it will take to do, and worse it’s very hard to see how far you are through the process. The result is that you are putting yourself into a complete blind spot right at one of tensest parts of a project.
Because CI integrates and runs tests and inspections several times a day, there is a greater chance that defects are discovered when they are introduced. Continuous Integrations doesn’t get rid of bugs, but it does make them dramatically easier to find and remove.
Health of software can be measured: By incorporating continuous testing and inspection into the automated integration process, the software product’s health attributes, such as complexity can be tracked over time.
2. Reduce repetitive manual processes
Reducing repetitive processes saves time, cost & effort.
By automating CI, we have a greater ability to ensure all of the following:
- The process runs the same way everywhere.
- An ordered process is followed.
- The processes will run every time a commit occurs in the version control repository.
3. Generate deployable software at any time & at any place
CI can enable us to release deployable software at any point in time.
With CI, we make small changes to the source code and integrate these changes with the rest of the code on a regular basis. If there are any problems with the recently integrated code, the team gets the feedback so that they can fix it immediately. Hence, the code on this mainline branch is always ready to be deployed to production.
4. Eliminate “Works on my machine” problems
We all have gone through the phase where the code “works on our machine” but fails miserably on build server or another developer’s machine right?
CI can help us eliminate this problem by providing us fast feedback the moment we push the code to version control rather than at the end of sprint (or even worse, just before sprint review or big demo to the stakeholders!).
5. Enable better project visibility
CI has following positive effects in terms of providing us with noticeable trends
- A CI system can provide just-in-time information on the recent build status & quality metrics.
- Since integrations occur frequently with a CI system, the ability to notice trends in build success or failure, overall quality & another pertinent project information becomes possible.
6. Establish greater Product confidence
Without frequent integrations, some teams may feel stifled because they don’t know the impacts of their code changes. Since a CI system can inform you when something goes wrong, developers and other team members have more confidence in making changes.
CI Best Practices
Now that we have seen the benefits of Continuous Integration, let us take a look at some best practices that we, as a team, should follow to reap these benefits: –
1. Commit code frequently
One of the central tenets of CI is integrating early and often. Developers must commit code frequently in order to realize the benefits of CI.
Each team should try to follow one or both of these techniques to commit code more frequently:
- Make small changes: Try not to change many components all at once. Instead, choose a small task, write the tests and source code, run the tests & then commit your code to the version control repository.
- Commit after each task: Tasks should be broken up in such a way that they can be finished in a few hours. Once this task is complete & tests against the source code are running, commit the code.
2. Don’t commit broken code
A dangerous assumption on a project is that everyone knows not to commit code that does not work, on to the version control repository. Yet it happens so many times that we commit code to the repository which breaks because of a test failure.
Solution to this problem is to make it part of the team’s accepted development practice to always run a private build before committing code to the repository.
3. Fix broken builds immediately
A broken build is anything that prevents the build from reporting success. This may be a compilation error, a failed test or inspection, a problem with the database or a failed deployment.
A key part of doing a continuous build is that if the mainline build fails, it needs to be fixed right away. The whole point of working with CI is that you’re always developing on a known stable base.
It’s not a bad thing for the mainline build to break, although if it’s happening all the time it suggests people aren’t being careful enough about updating and building locally before a commit. When the mainline build does break, however, it’s important that it gets fixed fast.
4. Continuous testing (which can be run automatically)
If we are to build software systems that are truly reliable, then we have to ensure reliability at the object level, which can be only achieved through successful unit testing. Otherwise we can’t possibly hope to build highly reliable applications.
The same applies to component testing which can help us to verify that multiple components interacting with each other are working as expected.
The same applies to component testing or system testing or functional testing. In order to run tests for a CI system, the tests must be automated.
5. All tests and inspections must pass always
In a CI environment, 100% of a project’s automated unit & component tests must pass for a build to be certified as PASS. These tests are as important as compilation. Accepting code that does not pass the tests can lead to lower-quality software.
6. Run private builds
To prevent broken builds, developers should emulate an integration build on their local workstation IDE after completing their unit tests.
This build allows us to integrate our new working software with the changes from version control repository.
7. Avoid getting broken code
When the build is broken, don’t pull the latest code from the repository. Otherwise, we might spend time developing a workaround to the error known to have failed the build, just so that we can compile and test our code.
Instead just pair with the team member whose code has broken the build. This will help you to get the stable build back up.
8. Use a Version Control repository to share database assets
All software assets, such as the ones mentioned below should be pushed to version control repository:
- DDL to drop and create tables and views, including constraints and triggers.
- Stored procedures and functions.
- Entity relationships diagrams
- Test data for different environment
- Specific database configuration
The goal should be to recreate the entire database from “scratch” using the scripts in the version control repository. This goal can be achieved if we have scripts for all the database objects in version control.
9. Run faster tests first & keep the builds fast
The whole point of Continuous Integration is to provide rapid feedback. Nothing sucks the blood of a CI activity more than a build that takes a long time. Typically, the majority of a build’s runtime is spent on tests, and the longest tests are those with dependencies on outside objects such as databases, file systems and web containers.
Unit tests should run more often (with every commit). Component tests, system tests and functional tests can be run with secondary builds or on periodic intervals.
10. Maintain organizational standards with code audits
While both human code reviews and pair programming can be effective in monitoring coding standards, they do not scale as well as automated tools. Not only do tools contain hundreds of rules (that are usually customizable), they can be run frequently and usually without intervention.
In a CI environment, a code analysis tool can be run any time a change is made to the repository.
Code analysis tools like PMD, Checkstyle can report complexity metrics like cyclomatic complexity, long methods, long classes, unnecessary verbose code, a poorly named methods/classes/variables.
By continuously monitoring and auditing code, your team can stay on track with architectural and coding guidelines.
Adopting these best practices will allow us to create a process with increased productivity, faster time to market, reduced risk and increased quality.
Thanks for reading. If you have some feedback or want to share some experience or have some questions, please leave a comment.
- Continuous Integration book by Paul M. Duvall with Steve Matyas &Andrew Glover
- Blog by Martin Fowler: https://martinfowler.com/articles/continuousIntegration.html#BenefitsOfContinuousIntegration