Setting up a CI/CD pipeline is not about picking a tool and writing a YAML file. It is about designing a reliable, fast, and secure delivery system that your team will actually trust. This guide walks through the entire process — from tool selection to production monitoring.

Read also: Kubernetes Implementation Checklist for Production | Cloud Migration Checklist: Step-by-Step Guide

Step 1: Choose the right CI/CD tool

The tool you pick determines your constraints for the next 3-5 years. Choose based on your actual requirements, not popularity.

Decision matrix

CriteriaJenkinsGitHub ActionsGitLab CI
InfrastructureSelf-hosted (you manage servers)Cloud-managed (GitHub hosts runners)Cloud-managed or self-hosted
Setup timeDays to weeksMinutes to hoursHours to a day
Plugin ecosystem1,800+ plugins (variable quality)20,000+ marketplace actionsBuilt-in features, fewer extensions
Pipeline as codeJenkinsfile (Groovy)YAML workflows.gitlab-ci.yml (YAML)
Container registryRequires pluginGitHub Packages (built-in)Built-in registry
Security scanningPlugins requiredThird-party actionsBuilt-in SAST, DAST, dependency scanning
Cost (small team)Server costs ($50-200/month)2,000 free minutes/month400 free minutes/month
Best forComplex enterprise pipelinesGitHub-native projectsAll-in-one DevOps platform

When to pick each tool

GitHub Actions — your code is on GitHub, you want fast setup, and you prefer managed infrastructure. Best for teams of 2-50 developers.

GitLab CI — you want source code management, CI/CD, container registry, and security scanning in one platform. Best for organizations that want to consolidate tools.

Jenkins — you have existing Jenkins infrastructure, complex multi-branch pipelines with custom logic, or hard requirements for on-premises execution. Be aware that Jenkins requires ongoing maintenance — someone must manage the server, update plugins, and handle scaling.

Step 2: Design the pipeline architecture

Before writing configuration files, define what your pipeline needs to do.

Pipeline stages (in order)

  1. Source — trigger on push, pull request, or tag
  2. Build — compile code, build containers, generate artifacts
  3. Unit tests — fast tests that run in seconds, no external dependencies
  4. Integration tests — tests against real databases, APIs, or message queues
  5. Security scan — SAST (code), SCA (dependencies), container image scanning
  6. Artifact publish — push container images or packages to registry
  7. Deploy to staging — automatic deployment to pre-production environment
  8. Acceptance tests — end-to-end tests against staging
  9. Deploy to production — manual approval gate or automatic with canary
  10. Post-deploy validation — smoke tests, health checks, metric comparison

Speed targets

StageTarget durationIf slower, consider
BuildUnder 3 minutesMulti-stage Docker builds, layer caching
Unit testsUnder 5 minutesParallel test execution, test splitting
Integration testsUnder 10 minutesTestcontainers, parallel suites
Security scanUnder 5 minutesIncremental scans, baseline suppression
Full pipelineUnder 20 minutesParallelize independent stages

A pipeline that takes over 30 minutes will be bypassed by developers. Speed is not optional.

Step 3: Set up the build stage

Container build best practices

Use multi-stage builds to keep final images small and secure:

# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build

# Production stage
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]

Build caching

Caching reduces build times by 50-80%. Configure it per tool:

  • GitHub Actions: actions/cache for dependencies, Docker layer caching with docker/build-push-action
  • GitLab CI: cache: directive for dependencies, kaniko cache for container builds
  • Jenkins: persistent workspace volumes, Docker BuildKit cache mounts

Artifact versioning

Tag every artifact with a unique, traceable version:

  • Format: {service}-{semver}-{short-sha} (e.g., api-1.4.2-a3f9b21)
  • Never use latest in production — it is not reproducible
  • Store build metadata: commit SHA, branch, build number, build timestamp

Step 4: Integrate testing

Test pyramid in CI/CD

LayerCountSpeedRuns on
Unit testsHundreds to thousandsMilliseconds eachEvery commit
Integration testsDozens to hundredsSeconds eachEvery commit
E2E tests10-50 critical pathsMinutes eachPre-deploy to staging
Performance tests3-5 scenariosMinutesNightly or pre-release

Parallel test execution

Split tests across multiple runners to cut execution time:

  • GitHub Actions: use a matrix strategy to run test suites in parallel
  • GitLab CI: use parallel: keyword with test splitting
  • All tools: split by test file, module, or timing data (slowest tests first)

Quality gates

Define gates that block deployments:

  • All unit and integration tests pass (zero tolerance)
  • Code coverage does not drop below baseline (e.g., 80%)
  • No critical or high vulnerabilities in security scan
  • No lint errors
  • Performance benchmarks within 10% of baseline

Step 5: Choose a deployment strategy

Rolling update (default)

Replace instances one at a time. Simple, no extra infrastructure. Risk: both old and new versions serve traffic simultaneously during rollout.

Best for: internal services, APIs with backward-compatible changes.

Blue-green deployment

Run two identical environments. Deploy to the idle one, validate, switch traffic.

Best for: applications where you need instant rollback and can afford double infrastructure during deployment.

Canary deployment

Route 1-5% of traffic to the new version. Monitor error rates and latency. Gradually increase to 100%.

Best for: high-traffic user-facing applications where you want to limit blast radius.

Implementation checklist

  • Choose strategy per service (not one strategy for everything)
  • Configure health checks: liveness, readiness, and startup probes
  • Define rollback triggers: error rate exceeds 1%, p99 latency exceeds 2x baseline, health check failures
  • Automate rollback — do not rely on a human watching dashboards at 3 AM
  • Test rollback procedure monthly

Step 6: Set up monitoring and alerts

Pipeline monitoring

Track these metrics for every pipeline:

  • Build frequency: how often the pipeline runs (target: multiple times per day)
  • Build duration: total pipeline time (target: under 20 minutes)
  • Build success rate: percentage of green builds (target: above 95%)
  • Mean time to recovery: how fast you fix a broken build (target: under 1 hour)
  • Deployment frequency: how often you deploy to production (target: daily or more)

Production monitoring post-deploy

After every deployment, automatically verify:

  • Health check endpoints return 200
  • Error rate has not increased compared to pre-deploy baseline
  • Response latency (p50, p95, p99) is within expected range
  • No increase in exception count in error tracking (Sentry, Bugsnag)
  • Key business metrics are not degraded (conversion rate, transaction volume)

Alerting rules

ConditionSeverityAction
Build broken on main branchCriticalNotify team immediately (Slack, PagerDuty)
Pipeline duration exceeds 30 minutesWarningInvestigate caching and parallelization
Deployment failureCriticalAuto-rollback, notify on-call
Post-deploy error rate above 1%CriticalAuto-rollback, page on-call engineer
Security scan finds critical CVEHighBlock deployment, create ticket

Common mistakes and how to avoid them

MistakeImpactFix
No caching20-minute builds that should take 5 minutesCache dependencies and Docker layers from day one
Tests depend on shared stateFlaky tests that erode trust in the pipelineIsolate tests — each test creates and cleans its own data
Secrets in pipeline configCredentials exposed in logs or repo historyUse secret management (GitHub Secrets, GitLab CI Variables, Vault)
No deployment approval for productionAccidental production deploymentsRequire manual approval gate before production deploy
Ignoring pipeline metricsSlow pipelines, frequent failures, nobody noticesDashboard with build duration, success rate, deployment frequency
Monolithic pipelineOne failing stage blocks everythingModularize into reusable workflows or templates

How ARDURA Consulting accelerates CI/CD implementation

Building a production-grade CI/CD pipeline requires experience with infrastructure automation, container orchestration, security tooling, and cloud platforms. ARDURA Consulting provides:

  • Experienced DevOps engineers — from our pool of 500+ senior specialists, we match engineers with hands-on CI/CD experience within 2 weeks
  • Platform engineers who have built pipelines for teams of 10 to 500 developers across GitHub Actions, GitLab CI, and Jenkins
  • Infrastructure as Code expertise — Terraform, Pulumi, and CloudFormation for pipeline infrastructure
  • 40% cost savings compared to hiring equivalent DevOps talent directly in Western Europe
  • 99% retention rate — our engineers stay with your project, providing continuity and knowledge retention
  • 211+ completed projects across software development, infrastructure, and DevOps

Ready to set up your CI/CD pipeline? Contact ARDURA Consulting for experienced DevOps engineers who can deliver a production-grade pipeline in weeks, not months.

Key takeaways

  1. Choose your CI/CD tool based on where your code lives and how much infrastructure you want to manage — GitHub Actions for GitHub repos, GitLab CI for all-in-one, Jenkins only for complex on-prem requirements
  2. Design the pipeline before writing configuration — define stages, speed targets, quality gates, and deployment strategy upfront
  3. Speed matters — a pipeline over 30 minutes will be bypassed by developers, invest in caching and parallel execution from the start
  4. Automate rollbacks with clear triggers (error rate, latency, health checks) — manual rollback at 3 AM is not a strategy
  5. Monitor the pipeline itself — track build duration, success rate, and deployment frequency as first-class metrics