Skip to content

Introduction to Continuous Integration

The Story

A team of scientists is working on a little project that takes astronaut data from Wikidata to analyse the time humans spent in space as well as the age distribution of the astronauts. The project quickly gained attraction and a lot of users as well as contributors joined the project. After some time it became hard for the maintainers to ensure new functionality is properly tested. It also frequently happened that contributors followed a different code style or forgot to add license information.

Verifying those criteria manually is tedious and not promising in the long run. This is why the team aims at automating as much as possible to save their valuable time. Luckily, they found a tool called GitLab CI which they can use to automate those tasks. In the following we will learn what GitLab CI and Continuous Integration is all about.

XKCD - Is it worth the time?
Is it worth the time? - licensed under a Creative Commons Attribution-NonCommercial 2.5 License .

This comic shows the relation between duration of a task, its repetitions and the time this task consumes - if task-execution is done by hand. We are speaking of weeks or even months of work over the course of time. Automating this part of the process thus can save a substantial amount of time.

What is Continuous Integration?

Martin Fowler is a renowned software architect and author, well-known for his influential work on agile development, refactoring, and patterns of enterprise application architecture.

In one of his articles he described Continuous Integration as follows:

“Continuous Integration is a software development practice where each member of a team merges their changes into a codebase together with their colleagues changes at least daily. Each of these integrations is verified by an automated build (including test) to detect integration errors as quickly as possible.” — Martin Fowler

Practices of Continuous Integration

In the very same article about Continuous Integration Martin Fowler also wrote about practices of Continuous Integration. Here, we will summarize these eleven practices very briefly.

1 Put everything in a version controlled mainline

The team should store all source code, configuration files, and database schemas in a single, shared mainline. This ensures that any developer can clone the repository and build the entire system without needing external manual setup. By treating everything as versioned text, the team can easily track changes and understand the project’s history. This practice eliminates the confusion and risk associated with managing multiple diverging branches.

2 Automate the Build

The process of turning source code into a running system must be fully automated to prevent human error and wasted effort. Using tools that support a “dependency network” allows the system to only rebuild the parts that have actually changed. All build instructions must be stored in the repository as text to ensure they are versioned and transparent. This automation ensures that a product can be reliably recreated at any time with a single command.

3 Make the Build Self-Testing

A successful build must be defined by passing a comprehensive suite of automated tests rather than just compiling. This provides a critical safety net that prevents bugs from leaking into the mainline and disrupting other developers. The team should strive for a state where a “green” build guarantees that no significant defects are present. Consequently, writing tests becomes a core part of the development process, not an afterthought.

4 Everyone Pushes Commits To the Mainline Every Day

Frequent integration serves as a continuous communication channel, alerting developers to conflicts almost as soon as they occur. By pushing changes daily, the amount of work to be integrated remains small and manageable. This prevents the “integration hell” that occurs when large feature branches diverge over several weeks. It encourages developers to break their work into small, deliverable chunks of a few hours each.

5 Every Push to Mainline Should Trigger a Build

A Continuous Integration service should automatically verify every commit in a clean reference environment. This step eliminates the “works on my machine” problem by ensuring the code is portable and correctly configured. Because the build is triggered by every push, the team can isolate the exact change that caused a failure. This automated vigilance keeps the mainline in a constant state of health.

6 Fix Broken Builds Immediately

Maintaining a healthy mainline is the highest priority for the team, as a broken build blocks everyone’s progress. When a failure occurs, the team should act immediately to fix it or revert the faulty commit. Reverting is often the preferred option as it restores stability quickly while the bug is analyzed offline. This discipline ensures that the mainline remains a reliable foundation for further development.

7 Keep the Build Fast

The effectiveness of CI depends on a rapid feedback loop, which requires a very fast build process. Teams should aim for a ten-minute build to ensure that developers are not discouraged from committing frequently. This is often achieved through a “deployment pipeline” that separates fast unit tests from slower, more exhaustive tests. Parallelism in the cloud can further reduce build times for larger projects.

8 Hide Work-in-Progress

Because integration happens daily, unfinished features are often pushed to the mainline before they are ready for users. Techniques such as feature flags, keystones, and branch-by-abstraction are used to hide this latent code from production. This allows the team to integrate and test the code continuously without risking the user experience. Once a feature is fully released, the toggles and flags are removed to keep the code clean.

9 Test in a Clone of the Production Environment

To avoid “environment-specific” bugs, the test environment must be an exact mimic of the production setup. This includes using the same operating system versions, database software, and network configurations. Tools like containers and Infrastructure as Code make it easier to replicate these environments reliably. This practice ensures that a “green” test result actually translates to success in the live environment.

10 Everyone can see what’s happening

Build status should be highly visible to the entire team through dashboards, notifications, or physical displays. When a build fails, the immediate visibility prompts the team to collaborate on a fix. Conversely, consistent “green” builds provide a psychological sense of progress and stability. This transparency fosters a culture of collective ownership over the quality of the product.

11 Automate Deployment

The process of moving software from the repository into test and production environments should be fully scripted to eliminate manual errors. This automation allows the team to deploy updates frequently and reliably, reducing the stress associated with release days. It also enables critical safety features, such as automated rollbacks, which can quickly restore the system if a bug is detected in production. Ultimately, this ensures that the decision to go live is a simple business choice rather than a complex technical struggle.

What does CI/CD refer to?

You might have heard of different terms like Continuous Integration, Continuous Delivery and Continuous Deployment. In order to mark their distinct features, the following sections are taken from GitLab.

Continuous Integration (CI)

“Continuous integration is the practice of integrating all your code changes into the main branch of a shared source code repository early and often, automatically testing each change when you commit or merge them, and automatically kicking off a build. With continuous integration, errors and security issues can be identified and fixed more easily, and much earlier in the development process.”

Continuous Delivery (CD)

“[Continuous delivery] is a software development practice that works in conjunction with CI to automate the infrastructure provisioning and application release process.

Once code has been tested and built as part of the CI process, CD takes over during the final stages to ensure it’s packaged with everything it needs to deploy to any environment at any time. CD can cover everything from provisioning the infrastructure to deploying the application to the testing or production environment.

With CD, the software is built so that it can be deployed to production at any time. Then you can trigger the deployments manually or move to continuous deployment, where deployments are automated as well.”

Continuous Deployment

“Continuous deployment enables organizations to deploy their applications automatically, eliminating the need for human intervention.”