In this article

Bad practices in continuous integration pipelines and processes

This catalogue of 79 bad smells can help you make your continuous integration processes less shitty.

Oh, nose!
Someone crawls into a giant nose

Oh, nose!

Continuous integration (CI) enables development teams to detect integration issues as early as possible. Some teams also use continuous delivery (CD), which allows for frequent code releases.

Adoption of CI can lead to a significant increase in productivity and customer satisfaction, so it’s probably not surprising that CI has become one of the most widely used software engineering practices. Nevertheless, adopting CI properly can be quite a challenge. Developers may struggle with automating the build process or debugging pipeline failures, or apply CI incorrectly.

This week’s paper empirically investigates what bad practices developers encounter when using CI in their daily development activities. Its authors conducted semi-structured interviews with 13 developers and manually analysed over 2,300 Slack Overflow posts. The result is a chonky catalogue of anti-patterns for continuous integration, which was evaluated using a survey.

The catalogue lists bad smells related to seven different categories: the repository, infrastructure choices, build process organisation, build maintainability, quality assurance, delivery process, and culture.

Repository

The first ten bad smells are related to the way the source code repository is organised and misuse of the version control system in the context of CI.

Survey respondents believe that only some of these bad smells are important in practice, particularly differences between local and CI workspaces, and not versioning pipeline resources.

Bad smellAgree (%)?Disagree (%)
Project decomposition in the repository does not follow modularisation principles39>30
Test cases are not organised in folders based on their purposes22<48
Local and remote workspace are not aligned57>30
Number of branches do not fit the project needs/characteristics27<41
A stable release branch is missing45=45
Feature branches are used instead of feature toggles45>30
Divergent branches48>38
Generated artifacts are versioned, while they should not18<50
Blobs are unnecessarily checked in at every build instead of being cached23<41
Pipeline-related resources are not versioned64>18

Infrastructure choices

The second category of bad smells is related to a sub-optimal choice of hardware or software components for CI pipelines, e.g. poor allocation of resources or incorrect usage of CI tools.

Somewhat surprisingly, most smells in this category were received negatively by respondents. It’s likely that the increased availability of cheap computing and networking resources has essentially reduced some bad smells to non-issues.

Bad smellAgree (%)?Disagree (%)
Resources related to the same pipeline stage are distributed over several servers14<64
The CI server hardware is used for different purposes other than running the CI framework24<48
External tools are used with their default configurations28=28
Different releases of tools/plugins versions are installed on the same server48>40
Different plugins are used to perform the same task in the same build process28<48
A task is implemented using an unsuitable tool/plugin32<40
Use shell scripts for a task for which there is a suitable plugin available20<44

Build process organisation

The authors identified 29(!) bad smells that are related to poor configuration of a CI pipeline.

A fair number of the smells in this category were received positively by survey respondents, which is not surprising as many of the bad smells in this category directly impact the usability of a CI pipeline.

Bad smellAgree (%)?Disagree (%)
Inappropriate build environment clean-up strategy40>28
Missing package management58>25
Wide and incohesive build jobs are used40<44
Monolithic builds are used in the pipeline56>28
Independent build jobs are not executed in parallel36<48
Only the last commit is built, aborting obsolete and queued builds24<44
Build steps are not properly ordered48>40
Pipeline steps/stages are skipped arbitrarily46=46
Tasks are not properly distributed among different build stages35<48
Incremental builds are used while never building the whole project from scratch36=36
Poor build triggering strategy50>33
Private builds are not used36>32
Some pipeline tasks are started manually44=44
Use of nightly builds48>36
Inactive projects are being polled17<52
A build is succeeded when a task is failed or an error is thrown64>28
A build fails because of some flakiness in the execution, whereas it should not67>12
Dependency management is not used44>40
Including unneeded dependencies44>36
Some tasks are executed without clearly reporting their results in the build output56>24
The output of different build tasks are mixed in the build output48>17
Failure notifications are only sent to teams/developers that explicitly subscribed40<44
Missing notification mechanism56>28
Build reports contain verbose, irrelevant information56>24
Time-out is not properly configured52>36
Unneeded tasks are scheduled in the build process44>28
Build time for the commit stage overcomes the 10-minutes rule52>22
Unnecessary re-build steps are performed40>20
Authentication data is hard-coded (in clear) under VCS52>32

Build maintainability

Build configurations can be harder to maintain, because changes to configuration generally incur more relative churn than changes to source code.

Reception to the bad smells in this category was mixed, possibly because some bad smells do not apply to all types of projects.

Bad smellAgree (%)?Disagree (%)
Absolute/machine-dependent paths are used65>31
Build scripts are highly dependent upon the IDE58>27
Environment variables are not used at all31<35
Build configurations are cloned in different environments29<50
Build jobs are not parametrised36=36
Lengthy build scripts28<40
Missing smoke test, set of tests to verify the testability of the build44>24
Missing/poor strict naming convention for build jobs46>15

Quality assurance

Testing and static analysis are important steps in most CI pipelines, but both are easy to mess up.

Most respondents agreed that these bad smells are harmful in practice and should be mitigated whenever possible.

Bad smellAgree (%)?Disagree (%)
Lack of testing in a production-like environment75>8
Code coverage tools are run only while performing testing different from unit and integration35>30
Coverage thresholds are fixed on what reached in previous builds30<35
Coverage thresholds are too high25<46
Missing tests on feature branches50>31
All permutations of feature toggles are tested37>32
Production resources are used for testing purposes52>36
Testing is not fully automated leading to a non-reproducible build65>27
Test suite contains flaky tests69>19
Bad choice on the subset of test cases to run on the CI server40>28
Failed tests are re-executed in the same build20<52
Quality gates are defined without developers considering only what dictated by the customer42>29
Use quality gates in order to monitor the activity of specific developers52>36
Unnecessary static analysis checks are included in the build process42>28

Delivery process

This category of bad smells is about the artefacts that are generated after a successful pipeline build.

All smells in this category were assessed positively by respondents, i.e. they should be taken into account by teams that want to improve their delivery process.

Bad smellAgree (%)?Disagree (%)
Artefacts locally generated are deployed58>35
Missing artefacts’ repository46>35
Missing rollback strategy62>15
Release tag strategy is missing50>27
Missing check for deliverables62>25

Culture

Some bad smells are not related to the CI pipeline itself, but the people who use it.

Again, all bad smells in this category are believed to be at least somewhat important by survey respondents.

Bad smellAgree (%)?Disagree (%)
Changes are pulled before fixing a previous build failure43>30
Team meeting/discussion is performed just before pushing on the master branch36>32
Developers and operators are kept as separate roles44>24
Developers do not have a complete control of the environment46>19
Build failures are not fixed immediately giving priority to other changes58>12
Issue notifications are ignored64>16

Summary

  1. I can’t and am not going to summarise 79 different bad smells. Just look at the tables and do whatever you need to do, okay?! 😩