What Is a CI/CD Pipeline?

The Ultimate Guide to CI/CD

What exactly is a continuous integration/continuous delivery pipeline? And how do you make one?

If you’ve been reading up on continuous integration and delivery and deployment (collectively known as CI/CD), you’ve almost certainly come across the term “automated pipeline” and learned about how it plays a central role in implementing these practices.

CI/CD is a DevOps practice that helps you deliver software faster without compromising on quality. CI/CD involves committing changes frequently, testing these updates rigorously, and addressing feedback promptly. Having an automated CI/CD pipeline is essential to this way of working.

What is a CI/CD pipeline?

When we talk about a CI/CD pipeline, we’re referring to the process that takes code from your development environment through various steps like testing and staging, ultimately delivering it into your users’ hands.

The aim of CI/CD is to execute this process regularly – multiple times per day or even per hour – so it’s essential to automate as much of your CI/CD pipeline as possible. If a step completes successfully, it should trigger the next one automatically. If a step fails, that feedback should be communicated quickly so the problem can be fixed.

Automating your CI/CD pipelines not only speeds up the overall process of building, testing, and deploying software, but it also ensures that each step is performed consistently and reliably.

The stages of a build pipeline

Although the exact shape of your CI/CD pipeline will depend on your product and your organization, there is a general pattern that all pipelines tend to follow:

  1. The process begins with a commit to main (or whichever branch you’ve nominated as the CI branch), which triggers either a build or an initial set of unit tests. The results are typically visible on a dashboard. The pipeline can be designed to halt on build or test failures, allowing you to address any issue before continuing. Once a fix is committed, the pipeline automatically restarts from the beginning to ensure everything is working as intended. Alternatively, you can configure the pipeline to continue while flagging failures for investigation.
  2. The next stage involves a series of automated tests, with feedback provided after each round of testing. Tests are usually structured so that the quickest tests are run first, thereby providing feedback as early as possible. Resource-intensive tests run last, but only if all preceding steps have completed successfully. Again, if any test fails, you might stop the pipeline and start over, or continue while raising the issue for investigation.
  3. Once automated tests have completed, the software is typically deployed to a series of staging environments. Some of these may be used for further manual testing while others may be used for training, support, and customer previews.
  4. The final stage of the CI/CD pipeline architecture involves making the changes live. The release can either be triggered manually (in the case of continuous delivery) or automatically (as with continuous deployment).

Let’s dive deeper into some key considerations for each of these stages.

CI/CD Best Practices

Building a CI/CD pipeline should not be a fire-and-forget exercise. Explore CI/CD best practices for your pipeline.

Flags and branches

The first step in adopting continuous integration is to get your entire codebase into a version control system or VCS (aka source control management or SCM), such as Git, Mercurial, or Perforce, and then to get everyone on your team into the habit of committing their changes frequently. Each commit to main initiates the continuous integration pipeline, building and testing the code to provide rapid feedback on the latest changes.

While frequent commits are an important practice in the CI/CD pipeline, if you’re working on a larger feature that will take several days or weeks to complete, then committing periodically during that process can feel slightly counterproductive.

On the one hand, pushing your changes through the pipeline in regular increments provides you with rapid feedback. It also makes complex merge conflicts less likely than if you wait until you’ve completed the feature.

On the other hand, pushing unfinished features through the pipeline might not be ideal. Sharing incomplete work with users, even in staging environments, might not be desirable either.

Feature flags and feature branches offer ways around this issue. With feature flags, you specify the environments in which your code is visible to users. Your changes are still committed to main and visible to your team, but you decide when the functionality becomes available in staging and production.

Feature branches allow you to develop your feature in a separate branch without losing out on the benefits of automated builds and tests. By triggering the CI/CD pipeline on each commit to a feature branch, just as you would with a commit to main, you can get rapid feedback on what you’ve built.

Build and test

Having triggered an instance of your pipeline with a commit, the next stages are building and testing. If you have automated unit tests, these are usually run before the build, alongside linting and static analysis checks.

The build tool you use (such as Ant or Maven), and the details of the build steps will depend on the language and framework you’re working with. By running the automated build on a dedicated build server, you can avoid issues further down the line caused by missing dependencies – the classic “works on my machine” problem.

The build step produces the application artifacts, which can include installers, binaries, or containers. These artifacts are then deployed to testing environments and integrated with other system components to run higher-level automated tests: integration tests, component tests, and end-to-end tests, as well as non-functional testing, such as performance and security analysis.

These tests may be run in parallel to speed up the pipeline and provide you with feedback faster.

Automated Testing for CI/CD

Learn why testing is so important for the CI/CD process and what kinds of tests there are.

Containers vs. VMs

For the results of your automated tests to be reliable, you need to ensure they run consistently.

Ideally, your test environments should be configured to resemble production as closely as possible, and they should be reset between test runs to avoid environmental inconsistencies disrupting your test results.

Virtual machines (VMs) have long been a popular choice for running test environments, as you can script the process of refreshing them for each new build under test.

However, tearing down and spinning up new VMs takes time, while your scripts will need to include configuration for each virtual environment to provide all the dependencies the software needs to run. When new dependencies are added, the environment scripts will need to be updated – an easy detail to miss until you’re wondering why your build won’t run.

You can avoid these issues by packaging your code in a container as part of the initial build step. A container includes all the dependencies that the software needs to run, making it highly portable and easier to deploy to different environments.

If you’re hosting your CI/CD pipelines on your own infrastructure, you’ll still need VMs to deploy the containers to, but there is less work involved in preparing the test environments. If you’re running your pipeline in the cloud, using containers means you can take advantage of managed services and offload the infrastructure management to your cloud provider.

Pre-production environments

The number of testing and staging environments in your pipeline architecture will depend on what you’re building and the needs of the different stakeholder groups in your organization. Examples include exploratory testing, security reviews, user research, sales demos, training environments, and sandboxes for support staff to replicate customer issues.

Automating the creation of and deployment to these environments is more efficient than refreshing them manually. You can also configure different pipeline triggers for different environments.

For example, while your test environments might be updated with every build, you may decide to refresh staging environments less frequently – perhaps once a day or once a week with the latest successful build.

Deploy

Once your code changes have passed each of the previous pipeline stages successfully, they are ready for release to production. This final step can be either manual or automatic.

Releasing manually (continuous delivery) is useful if:

  • You want to control when new features or functionality are made available.
  • Your deployment process involves downtime for your users.
  • Users need to install your product, and you want to batch up changes for delivery on a regular release schedule.

With continuous deployment, the release is automatic. Changes go live providing they have passed all previous stages. For larger teams that commit frequently, this can mean deploying updates to users dozens of times per day – a feat that is practically impossible without an automated pipeline.

CI/CD tools

Dedicated tools play an important role in building a CI/CD process, but that doesn’t mean you can’t get started without them. Initially, you might choose to focus on writing automated tests and scripting them to run automatically, without the help of a CI/CD platform.

This might then gradually evolve into a continuous integration pipeline with build and tests jobs that run on a schedule.

Selecting the right CI/CD tool for your needs will also help roll out your CI/CD strategy faster – from adding more pipelines to managing and scaling build infrastructure more efficiently.

To help you choose the best CI/CD tool for the job, we’ve put together a list of things to consider:

  • Integration options: Your CI/CD tool needs to integrate with your VCS, build tools, testing frameworks, and package managers so it can coordinate each stage of your CI/CD pipelines. It should also integrate with your team’s messaging platforms, issue tracker, and IDEs so you can get feedback where you want it.
  • Tech stack support: Consider not only the programming languages, platforms, and frameworks you’re currently using, but also how your needs are likely to evolve. Tools that are in active development are most likely to support new technology.
  • Interfaces for everyone: Having a choice of GUI, API, and CLI becomes important as you bring more people into your CI/CD process. Support for configuration-as-code is vital if you want to take a full DevOps approach.
  • Customizability: There’s no standard CI/CD pipeline, so choose a tool that gives you the flexibility to build the automated process that meets your needs.
  • Infrastructure options: You may want to host your pipeline on in-house servers for security or compliance reasons. You may be a fully cloud-based organization or you may be planning to migrate to the cloud in future. Whatever your preference, make sure your chosen tool supports both your current and future needs.
  • Scalability and performance: As you create pipelines for more projects and run your pipelines more frequently, infrastructure can become a limiting factor. Choosing a CI/CD tool that can scale and streamline management of your build and test machines will save time and effort.
  • Cost: As well as the license fee, consider the cost of support and options for cloud-hosted infrastructure.

How to Choose a CI/CD Tool

In this blog post, we offer general guidelines for selecting an appropriate CI/CD solution and delve into how TeamCity fits into this framework.

What is CI/CD in DevOps?

CI/CD forms part of a wider practice known as DevOps. Combining development (creating software products and services) with operations (releasing and maintaining that software), DevOps is both a way of working and a mindset. It builds on Agile principles to help the wider organization – not just development teams – deliver quality software faster.

When implementing your CI/CD pipelines, understanding what DevOps means will help you get started. The following points are worth bearing in mind:

  • DevOps emphasizes the importance of aligning everyone involved in the creation, release, and maintenance of software around a common goal: delivering working software that meets users’ needs.
  • Central to a DevOps approach is the concept of shifting left. This means finding out about problems as early as possible so they don’t create delays later in the process. That’s why CI/CD focuses on regular and rapid feedback loops, which help you shift left.
  • Bringing developer skills and expertise into operations opens up the possibility of automating tasks like maintaining infrastructure and refreshing environments.
  • By exposing development teams to work typically handled by operations teams, developers gain visibility into the entire process, allowing them to proactively address bugs and user feedback.

With CI/CD pipelines, you can automate what happens from when you commit changes to when you release a new version of your software. Automating these tasks accelerates execution, delivering feedback faster, which in turn allows necessary action to be taken earlier, potentially saving valuable time and resources.

Understanding CI/CD pipelines in a nutshell

CI/CD is a DevOps practice that uses automation to provide rapid feedback on each stage of the software development life cycle. Discovering issues introduced by your latest code changes makes software development more efficient. By shifting left (moving interactions earlier and getting feedback sooner), you are empowered to fail fast, and building an automated pipeline helps put these techniques into practice.

When it comes to designing your own CI/CD process, it’s a good idea to build it up in stages, starting with continuous integration. The exact stages of the pipeline and the logic determining when each stage is triggered depend on your product and your organization.

Choosing a CI/CD platform that provides the flexibility to configure your pipeline for your unique requirements, while still being easy to manage, will help you forge a dependable release process and improve the quality of your software.

How TeamCity can help

TeamCity is a CI/CD solution designed for a DevOps way of working. With support for all leading version control systems, a wide range of build, test, and package management tools, as well as popular VM and container management platforms, TeamCity helps you transform your existing processes into automated CI/CD pipelines.

Flexible trigger options and a visual pipeline editor make it easy to configure pipelines for any workflow. Configurations are automatically stored as code, giving you the freedom to build your logic in the GUI while leveraging all the benefits of configuration as code.

Thanks to TeamCity’s high-performance design, a single build server can handle thousands of projects. On-premises and cloud-native deployment options give you the flexibility to run your pipelines where you want and scale up on demand. Test parallelization and real-time results shorten feedback loops even more, helping you fail fast for a more productive developer experience.

Still have questions? Learn more in our FAQ section.