CI/CD: The Non-Negotiable Foundation

DevOps Quality Development
RJ Lindelof
June 10, 2026 8 min read DevOps Best Practices at RJL.dev
CI/CD: The Non-Negotiable Foundation

If you're still deploying manually, you're wasting time and shipping bugs. Here's how to build a CI/CD pipeline that actually works.

There's a simple test for engineering maturity: Can you deploy to production in under 15 minutes with confidence? If the answer is "no" or "it depends," you have a CI/CD problem. Manual deployments are slow, error-prone, and terrifying. Automated pipelines are fast, reliable, and boring - exactly what deployments should be.

What CI/CD Actually Means

Continuous Integration (CI) - Every code change automatically triggers:

  • Build verification - does it compile?
  • Automated tests - does it work?
  • Code quality checks - is it maintainable?
  • Security scans - is it safe?

Continuous Delivery (CD) - After CI passes:

  • Artifacts are built and stored
  • Deployment to staging is automatic
  • Production deployment is one click (or automatic)

The goal: code committed Monday morning can be in production Monday afternoon - safely, repeatably, without anyone staying late.

The Cost of NOT Having CI/CD

Deployment Fear

Without CI/CD, deployments become events. Teams batch up changes because deploying is painful. Releases get bigger and riskier. Friday deployments become forbidden. Everyone's afraid to ship.

Manual Error

Humans make mistakes. The deployment checklist says 20 steps, but someone skips step 14. The environment variables are different on staging and production. Someone forgot to run database migrations.

Slow Feedback

Without automated tests, bugs aren't found until QA - or worse, production. The developer who wrote the code has moved on to something else. Context is lost. Fixes take longer.

Bus Factor

Only Sarah knows how to deploy. Sarah is on vacation. Nothing ships until Sarah returns. This is an organizational risk, not just an inconvenience.

Essential Pipeline Stages

1. Lint

Catch style issues and obvious bugs before anyone looks at the code:

  • ESLint for JavaScript/TypeScript
  • Pylint/Ruff for Python
  • Prettier for formatting

Fast, catches obvious issues, no excuses for skipping.

2. Test

Automated tests prove the code works:

  • Unit tests - Individual functions and modules
  • Integration tests - Components working together
  • End-to-end tests - Full user flows

A pipeline without tests is just automated deployment of bugs.

3. Build

Compile, bundle, containerize - create the deployable artifact:

  • Build for production (not dev mode)
  • Generate source maps for debugging
  • Create Docker images if containerized

4. Security Scan

Catch vulnerabilities before they ship:

  • Dependency scanning - npm audit, Snyk, Dependabot
  • SAST - Static analysis of your code
  • Secret detection - No API keys in the repo

5. Deploy

Move the artifact to the target environment:

  • Staging first, always
  • Run smoke tests after deployment
  • Production with approval or automatically

Tools That Work

GitHub Actions

Best for: GitHub repos, simple to medium complexity

Pros: Tight GitHub integration, huge marketplace, free tier for public repos

Cons: YAML gets messy at scale, debugging can be frustrating

GitLab CI

Best for: GitLab users, complex pipelines

Pros: Best-in-class pipeline visualization, built-in container registry

Cons: Tied to GitLab, can be resource-heavy

Jenkins

Best for: Complex enterprise needs, maximum flexibility

Pros: Infinitely customizable, huge plugin ecosystem

Cons: Requires maintenance, Groovy scripting is painful, security history is rough

CircleCI

Best for: Fast builds, Docker-based workflows

Pros: Fast, good caching, Docker support

Cons: Pricing adds up, fewer integrations than GitHub Actions

My recommendation: Start with GitHub Actions. It handles 90% of use cases with minimal setup.

Your First Pipeline in 30 Minutes

For a typical JavaScript project:

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run lint
      - run: npm test
      - run: npm run build

That's it. Every push runs lint, test, and build. Failures block the merge. You now have CI.

Advanced Patterns

Blue-Green Deployment

Run two identical production environments. Deploy to "blue" while "green" serves traffic. Switch the load balancer. Instant rollback if something breaks.

Canary Releases

Deploy to a small percentage of users first. Monitor for errors. Gradually increase traffic. If something breaks, only 5% of users noticed.

Feature Flags

Deploy code that's turned off. Enable features for specific users or percentages. Separate deployment from release. Fix bugs without rolling back.

Quality Gates

Don't let bad code through:

  • Test coverage threshold - Fail if coverage drops below 80%
  • No high-severity vulnerabilities - Block deploys with critical CVEs
  • Code review required - At least one approval before merge
  • All checks passing - No exceptions, no "just this once"

The Bottom Line

CI/CD isn't optional anymore. It's table stakes for professional software development. The investment pays off immediately:

  • Faster feedback on code changes
  • Fewer bugs reaching production
  • More frequent, smaller releases
  • Lower stress around deployments
  • Documentation in the form of pipeline code

Start simple. A basic pipeline running lint and tests is infinitely better than no pipeline. Add complexity as you need it.

If you're deploying manually, you're already behind. Fix that today.

Frequently Asked Questions

About the Author

RJ Lindelof is a technology executive with 35+ years of experience spanning Fortune 500 companies to startups. He does don't just talk about AI; he implement's it to solve real-world business problems. RJ's approach has led to significant improvements in team velocity, code quality, and time-to-market.