TechnologyFeb 16, 2018

3 Bad Continuous Integration Smells Part 1: Manually Invoking the Build

Eric Woods

Many companies have adopted the principles and practices of continuous integration (CI). It’s a way to meet the challenges of rapidly building, testing, and shipping software in a competitive landscape where efficiency, agility, and time to market are paramount. We are often asked to evaluate CI pipelines and make improvements. There are a few CI issues (or “smells”) that we routinely see that can negatively impact velocity, quality, and agility. In this series, we’ll review three common smells, what each one likely means, and what to do about it:

  1. Manually invoking the build.

  2. You build your application multiple times in the pipeline.

  3. Distinguishing the functional difference between build artifacts is difficult.

For part one we’ll explore the problem of manually invoking the build.

Smell 1: You Manually Invoke Your Build

If you’re doing this, it is all but certain that you’re not practicing CI. Lack of CI can lead to low velocity and poor code quality.

Fundamentally, CI is a practice where:

  1. On a regular basis, all developers pull from and push commits to the trunk of a repository in a version control system (VCS).

  2. Each commit to the trunk immediately and automatically invokes a build, including any functional, integration, and other quality testing.

  3. Team members are immediately alerted when builds fail, so they can work together to fix the problem.

Practicing CI reduces time between divergent versions of the source code—those versions on developer laptops or long running feature branches (best avoided). It also helps ensure the physically merged code builds successfully and functions as expected.

Why Is This Code Divergence a Problem?

As time passes and additional code changes are introduced prior to building, it becomes more difficult to fix a broken build; developers lose context and merges become larger, more complex, time consuming, and error-prone. In some cases, the negative behavior resulting from a merge error may not manifest itself until much later when it is more costly to remedy. By then it may have already negatively impacted your end users.

When commits are small and each commit results in an automated build and test cycle, it’s far easier to identify and fix or revert any specific change that results in a failed build or test cycle.

Why Are Teams Manually Invoking Builds?

So what are some of the reasons application teams are manually invoking builds and not practicing CI?

1. Lack of automation infrastructure and proper configuration.

In most cases, there is simply a lack of automation infrastructure managing the build process—the company doesn’t have a CI server or the CI server isn’t integrated with the VCS. In the worst cases, developers only ever run the build on their local machines. To deploy to remote environments, a designated “build master” pulls the most recent version of code down to a local machine, runs the build locally to produce the executable, and manually uploads and runs the executable in a remote environment.

Many VCS and CI servers provide the capability for organizations to easily apply and derive the benefits of automated builds on code commit. First, set up a VCS and CI server for your team. Second, make sure the two systems are integrated so that the CI server kicks off a build whenever a commit lands in the trunk.

2. The build process takes too long.

Sometimes the build and testing process takes longer than the rate at which code is being committed to trunk. In such cases, it’s not feasible to build after every commit. Teams end up working around the issue by scheduling build times or manually invoking them on an ad-hoc basis.

The answer to this problem is usually to parallelize the build and test pipeline as much as possible or defer some testing to a later phase. Do you really need to run that load test for every commit? Probably not, so relax that constraint. But attempt to optimize the process before you decide to relax the criteria that define a successful integration.

In the next blog post, we’ll look at the second smell—builds that are coupled to an environment. In the meantime, if you have questions or would like more information please reach out to us at