If there’s one capability that separates high-performing engineering organisations from struggling ones, it’s software delivery. Not talent, not tooling, not architecture — delivery.
Continuous integration and continuous delivery (CI/CD) is the engineering practice that makes frequent, safe delivery possible. This post builds the CI/CD blueprint for cloud-native systems.
Why Frequent Small Releases Win
The research in Accelerate (Forsgren, Humble, Kim) is unambiguous: high-performing teams deploy more frequently and have lower change failure rates than low-performing teams. These aren’t trade-offs — more frequent deployment is correlated with better stability.
The intuition: a deployment of 10 small changes is less risky than a deployment of 100 changes. Each small change is easier to understand, easier to review, easier to roll back if something goes wrong.
Big bang releases are a risk accumulation strategy. Avoid them.
Cloud-Native in Eight Elements
Before getting into the pipeline, it’s worth stating what “cloud-native” means from a delivery perspective. Four central ideas:
- Containerisation — every workload is a container
- Orchestration — Kubernetes manages the containers
- DevOps — shared ownership of the full SDLC
- Continuous delivery — software is always in a deployable state
And eight elements that make it real:
- Immutable infrastructure
- Declarative configuration
- Microservices
- Dynamic scheduling
- Automated delivery pipelines
- Observability
- Self-healing
- Policy-as-code
SCM as SDLC Tempo Driver
Source control management (Git) is the heartbeat of the SDLC. Every significant step — feature start, code review, quality gate, deployment — should be triggered by a Git event.
We use GitHub Flow as the branching strategy:
mainis always deployable- Feature work happens on short-lived branches (hours to days, not weeks)
- PRs are the unit of review and the trigger for quality gates
- Merge to
maintriggers deployment to dev; tagged releases trigger staging/production
GitHub Flow is simple and it forces small, frequent merges. Long-lived feature branches are a smell — they mean large, risky merges.
The Containerisation Pipeline
Every service gets built into a container image in CI:
git push → CI trigger → build container image → tag with git SHA → push to registry
Key principles:
- Build once — the same image that passes tests gets deployed to every environment
- Tag with git SHA — gives you exact traceability from production back to the commit
- Never use
latest— in production, always pin to a specific image SHA or version tag
Dev Environment Per Branch
One of the most powerful patterns in cloud-native CI/CD: a full development environment per branch.
With Kubernetes, it’s feasible to spin up a complete stack for every feature branch:
feature-branch → CI → build image → deploy to dev/feature-xyz namespace → accessible at feature-xyz.dev.yourdomain.com
This gives developers and reviewers a live, isolated environment to test against before merging. It eliminates the “works on my machine” problem and makes PR review much more effective.
The namespace is torn down when the branch is deleted.
Quality Gates on PRs
Before any code can merge to main, it must pass a set of automated quality gates:
1. Unit Tests
Fast, isolated tests of individual components. Must pass with high coverage. Target: under 5 minutes.
2. Integration Tests
Tests that exercise the service against real (or realistic) dependencies. Slower, but catch integration bugs that unit tests can’t.
3. Static Security Scan (SAST)
Automated scanning for security vulnerabilities in code and dependencies. Fail the build on critical findings.
4. Code Quality Scan
Linting, static analysis, code smell detection. Sonarqube, CodeClimate, or similar.
5. Peer Review
At minimum one human review of every change. Security-sensitive changes require a security-aware reviewer.
All five gates are required. A merge that skips any of them is a risk that will eventually manifest as a production incident.
Build Once, Promote Everywhere
The golden rule of CI/CD: the same artifact that was tested is the artifact that runs in production.
Do not rebuild images between environments. Rebuilding introduces the possibility of differences — different dependency versions, different build environment state, different code if something was wrong with the first build.
The promotion pipeline looks like:
commit → build image (tag: git SHA) → push to registry
↓
deploy to dev (automatic on merge)
↓
automated test suite in dev
↓
promote same image to staging (manual or automatic)
↓
acceptance tests in staging
↓
promote same image to production (manual approval)
The image SHA is what gets promoted. The environments are different; the artifact is not.
ChatOps
ChatOps brings your deployment pipeline into your team’s communication tool (Slack, Teams, etc.).
Instead of logging into a CI dashboard to trigger or check deployments, you interact via chat commands:
/deploy sensor-api v1.4.2 to staging
/rollback sensor-api in production
/status sensor-api
The bot executes the commands, reports back, and logs everything in the channel. This gives the whole team visibility into what’s being deployed and when, without anyone needing to context-switch to a separate tool.
ChatOps also serves as an audit log: every deployment, every rollback, is recorded in the chat channel with a timestamp and the person who triggered it.
Infrastructure as Code
The Kubernetes manifests, Helm charts, Terraform configurations — all of this is code, and it lives in Git.
Changes to infrastructure go through the same review and quality gate process as application code. Separate repositories for app code and infrastructure config (GitOps pattern) is common and works well.
Use ArgoCD or Flux to apply infrastructure changes from Git automatically (GitOps). The cluster state is always reconciled with what’s in Git.
Summary
A complete cloud-native CI/CD pipeline:
- Developer pushes to feature branch
- CI builds image, runs unit tests
- Dev environment deployed from branch
- PR raised → quality gates run (unit, integration, security scan, code quality)
- PR reviewed and approved
- Merge to main → automatic deploy to dev
- Automated tests run in dev
- Manual promotion to staging → acceptance tests
- Manual approval → promote to production
- ChatOps notification to team
The goal is a pipeline where deploying to production is boring. Boring is good.