There’s almost always more than one way to do something. Continuous Integration and Continuous Deployment pipelines are no exception. Today I want to briefly describe a few models of CI/CD pipelines I’ve seen or read about.
CI/CD with GitFlow
I’ve said beore that GitFlow is anti-agile, and I stand by that. Nobody should ever use GitFlow. But it is unfortunately common, so included for completeness sake.
In this model, CI is usually nominal only (that is: this branching model encourages many long-lived branches, which means that integration is not actually continual). Each PR typically executes the complete automated test suite, and can only be merged into the development branch upon success.
At some point in the future, probably after several weeks of manual QA acceptance testing, someone merges all or a subset of the new features in the development branch into the mainline branch. At this point, some automation will deploy to production.
CI as a gate keeper for CD
Although I’ve not really worked this way, I’ve heard a number of pair- and mob-programming advocates who encourage committing directly to mainline advocate something like this. It’s also similar to the approach discussed in Kent Beck’s book Extreme Programming Explained.
Code is merged (integrated) into mainline frequently (often with every commit). This triggers the test automation pipeline, and if that pipeline succeeds, it may kick off a deployment (in XP Explained the builds were done nightly, rather than on each merge, but faster hardware these days makes this delay unnecessary except on the bulkiest of projects).
Perhaps the biggest drawback to this approach is that the mainline branch is not safeguarded against breakage, since the test automation runs after merge rather than before merge.
GitHub Flow, like GitFlow above, is really a branching model, but it has some implications and natural tendencies for CI/CD.
The typical GitHub Flow approach to CI/CD is that new changes are put into a pull request. Test automation runs against this pull request, and merging is only allowed into mainline if the tests pass. Once merged, the deployment is kicked off automatically.
This approach has the benefit that mainline is guarded against common breakage, since all regression tests must pass before merging. It is sometimes seen as introducing too many delays in the coding process. I tend to disagree, so long as PRs are kept small, and merged frequently, but there’s plenty of room for nuance and opinion here.
The final model on my list is one I’ve called Lean CD, and it’s basically an adaptation of GitHub Flow, without automation. Thus the name “Lean”, as in, start lean, and build up (the automation).
In this approach, you still create pull requests, but you don’t need to depend on automated testing. Instead, you depend on a human-executed checklist of actions to be performed to validate a change before the “Merge” button is pressed. Over time, you’ll naturally want to automate as many of those tasks as possible; the point is you don’t need to automate all the validation steps before benefiting from CI/CD.
In this model, as soon as code is merged into mainline, the automation takes over to deploy.
Of course these aren’t the only models or workflows. And there’s room for a lot of variation even amoung these four.
What workflow does your team use? What do you like or dislike about it?