Optimising Continuous Delivery


The deployment pipeline is a central idea in Continuous Delivery. It represents the channel through which ideas inside your business flow to the outside world so that they can be delivered to your users in the form of working software. First steps in creating a working deployment pipeline are very rewarding. They help to improve the quality of the software that you create and usually lead to happier users.

As teams mature in their adoption of Continuous Delivery though, the pipeline often begins to slow. We have more tests, we are testing more complex things, our software becomes more complex and more difficult to deploy.

How do we address these growing pains? What are the next steps, beyond the CD beginner’s basic automation? How do we optimise our pipelines to meet our needs as these needs grow?

This talk will address the growing pains in Continuous Delivery and describe some strategies to cope with them.”


Faster is better

What do we really want ?

idea => get it in the hands of our users and find out on how they use it

we optimise to get fast feedback => a repeatable reliable process to deploy software

If you employ an empirical approach on solving problems you drive out pretty much all of agile methodologies, devops principles …

What is the Scope of a Deployment Pipeline ?

a question I get regularly from my clients

we want the whole thing: we want an independently deployable thing

maybe we have a different system that consists of multiple independently deployable things => easy to add new things without impact on the system as a whole

Scope of a Deployment Pipeline is an independently deployable unit.

Where to Test - Branching ?

feature branches: any testing happening earlier before the merge doesn’t make sense, it only makes sense to test after the merge => deferring feedback, it takes longer to get feedback

we can test on the branch, but then we never test what gets into production

Feature Branches should be an exception when we cannot cope with the situation.

My advice to branching strategies:

don't branch
Don't Branch
DON'T BRANCH

The Pipeline is a Strategic Resource

  • it is our only channel to production
  • all change in production flows through it
  • so if it breaks or goes slow, the impact is enormous

Pipeline Problems

  • slow commit stage
  • slow acceptance stage
  • failing tests
  • intermittent tests
  • pipeline changes

Slow Commit Stage

commit stage:

  • compile
  • unit test
  • analysis
  • build installers

Ideal feedback cycle for this stage < 5min

good reason: when I make a change, if it takes longer than 5min, I tend to do something else => developers start to defer the commit

The commit stage is the most valuable Feedback-cycle in the Pipeline. => it is worth investing time, energy and money to this stage

Slow Commit Stage - Compilation

simple solution:

  • buy faster hardware
  • parallelise the build

decompose your system into independent modules or services: each with it’s own pipeline

but there are some dangers here:

  • This is not as easy as it first seems
  • Dependency Management is one of the really HARD problems in Computer Science.

Micro Services is no “Silver Bullet”: if you test your micro services together because you don’t trust it, you’re not doing micro services. Run your microservice pipelines independent of each other. If you’re building services independently.

Remember: Independently Deployable Units

Look at a modern build system: Gradle, Bazel, Buck, …

Try running the build from RAM Disk: good for I/O bound compilation cycles e.g. C, C++

again: this is a good place to invest engineering time

Slow Commit Stage - Testing

look to your tests !

commit tests should be mostly pure unit tests

  • don’t start the app
  • don’t write to disk
  • don’t write to the DB
  • don’t use the network
  • fake external dependencies

accept slow tests grudgingly

always think about efficiency when writing tests

  • use chicken counting (0, 1, many): don’t have tests that do thousands of loops, if you iterate over a loop, loop 3 times
  • use mocks & stubs

If a test never catches a bug, maybe have a think of if it’s useful

run tests in parallel

  • if this is difficult, your test isolation is poor - fix it

as a last resort: if you still can’t get it performant, only then think of moving the test in a later stage

Slow Commit Stage - Analysis

static analysis can give valuable feedback

it needs to pay for itself though: if the analysis doesn’t catch bugs, drop it !!

as a last resort: move the analysis out of the commit stage

as a last last resort: give up ! move analysis out of the pipeline

shortness of the feedback is more important

Slow Commit Stage - Installers

we want to test Release Candidates that may make it to production

if creating installers is slow, move it out of Commit Stage

this is fine because creating installers is not usually what creates problems

Human CI

CD is about optimising your process to keep the software in a releasable state

That means pipeline failures stop the line and fix it

Commit Strategies

optimisation: gated CI: we commit to the commit stage if the tests pass the commit stage commits into our version control system

Performance of the Commit Stage matters

Teams with a fast Commit Stage keep the build green

Slow Acceptance Tests

acceptance test stage

  • configure env
  • deploy in acc env
  • smoke test/health check
  • acceptance test

ideal feedback cycle for this stage < 45 min

=> I now have 5 to 6 attempts to fix a failing acceptance test

=> much more probability of keeping the tests green

Slow Acceptance Tests - Configure Env

consider rates of change of different layers: OS changes less often than the app

consider the use of Containers

Slow Acceptance Tests - Deploy

successful deployment ends with a running, working system

so for efficiency we need to consider

  • time to deploy
  • time to migrate data
  • time to start the system
  • time to validate the system

Time To Deploy:

  • keep deployable artefacts lean: keep the stuff you need and remove the stuff you don’t need
  • packaging strategy can make a big difference (layering in containers)
  • think about network/infrastructure constraints at deployment time: think about what you need, think about caching strategies
  • minimise data-sets, where you can: I am not a big fan of production data in acceptance env.
  • consider better modularisation - Independently Deployable services

Time To Start the system

  • minimise startup dependencies & ordering
  • invest in optimising the code executed during startup - make it efficient !

Slow Acceptance Testing - Testing

There is a common cycle:

  • teams start writing acceptance tests and run them all sequentially
  • as number of Acc Testing increases the time they take to deliver feedback lengthens
  • Teams paralyse Acc Testing tactically
  • Teams move to more strategic (automated) …

Treat Acceptance Test isolation seriously from day one !

we don’t have ordering problems of our tests, we don’t have sharing problems. => makes scaling up easy

Failing Tests

The efficiency of the feedback cycle is central to the ability of a team to keep tests green !

high performance trading company using C++: build lead time from 9h to 12m (we measured everything, we used RAM disks, …)

from then on: every single build had green tests

Continuous Delivery is about: Keeping the build in a releasable state

=> priorities fixing tests

=> reduce the lead time and this will help

Intermittent Tests

Some CI systems even support running failing tests several times !! Why???

  • if the test passes once and fails once how do you know which result is correct ?

Treat intermittent tests as failing tests

Last Resort: if you can’t fix it, is it really worth keeping it ?

Common Causes:

  • race conditions
  • poor test isolation
  • poorly designed ..

Finally Pipeline Changes

traditionally: CD tools are really poor at version control

remember: the deployment pipeline is a strategic resource

consider SLA’s for the pipeline changes

the pipeline is a complex system in its own right => acceptance tests for the pipeline and a deployment pipeline for the pipeline

Consider writing test cases for some pipeline behaviours

Consider Blue/Green deployment strategies for pipeline changes

Use “Infrastructure as Code” for all pipeline

And do take it seriously: consider the pipeline as the only route to production

Continuous Delivery as Competitive Advantage

it is not about the technical practices, it is about evaluating ideas in the hands of the users

=> learn, adapt, refine and exceed expectations

Questions

What do you think of Property Based Testing ?

I am not a big believer of Property Based Testing

I have the feeling that people use it because they don’t do TDD properly.

it seems to be there to optimise typing, I prefer optimise thinking

Acceptance Testing

at ThoughtWorks: a quite large amount of people didn’t liked what Jez and I were writing about

you tent to over test things using Acceptance Testing