top of page
Search

**The Modern DevOps Pipeline:

  • Writer: Mark Kendall
    Mark Kendall
  • 4 days ago
  • 5 min read

**The Modern DevOps Pipeline:



How to Give Developers Real Autonomy Without Breaking Production**


By Mark Kendall – Learn, Teach, Master





Introduction: Why DevOps Feels Harder Than It Should Be



Most DevOps pipelines didn’t start out broken.

They started out small.


One script.

One YAML file.

One clever hack to get a build out the door.


And then… growth.


Suddenly you have:


  • 30 repositories

  • 40 pipelines

  • 12 different ways to build

  • 9 different ways to deploy

  • And no one who can confidently answer:


    “Where does this logic actually live?”



Pipelines fail.

People blame GitLab, or YAML, or Kubernetes.

But the real problem is architectural.


Modern DevOps fails when structure, behavior, and environment are mixed together.


This article shows a simple, real-world pattern for building a modern CI/CD system that:


  • Gives dev teams real autonomy

  • Keeps production protected

  • Scales cleanly across teams

  • Is understandable and debuggable

  • Doesn’t require exotic tools or vendor magic






The Core Principle: Separate the Three Things



Every healthy DevOps system respects one rule:


YAML defines structure.

Scripts define behavior.

Variables define environment.


Once you separate those three concerns, almost everything else falls into place.





The Mickey Mouse Model 🐭



(The Mental Model That Makes Everything Obvious)


Think of your DevOps system as three circles:

        ( Central CI/CD Repo )

     ┌────────────────────────┐

     │  Job Templates (YAML)  │

     │  Bootstrap Defaults   │

     │  Runtime Scripts (.sh)│

     └───────────┬────────────┘

                 │ include

                 ▼

┌────────────────────────────────┐

│           App Repo              │

│   .gitlab-ci.yml (thin)         │

│   src/                          │

│   Dockerfile                    │

└───────────────┬─────────────────┘

                │ runtime

                ▼

     ┌────────────────────────┐

     │  Environment Resolution │

     │  (GitLab Variables)     │

     │  SCRIPT_BRANCH          │

     │  ENV_TIER               │

     │  TARGET_CLUSTER         │

     └────────────────────────┘


Left Ear → App Repo



What the app team owns.



Head → Central DevOps Repo



What platform or shared services owns.



Right Ear → Environment



What GitLab (or your CI system) injects at runtime.


That’s it.


That’s the whole system.





Layer 1: The App Repository (Thin by Design)



The app repo should not contain DevOps logic.


It should contain:


  • Application code

  • A Dockerfile or build config

  • A tiny .gitlab-ci.yml



Example:

include:

  - project: devops/cicd-templates

    file:

      - yaml_files/defaults.yml

      - yaml_files/templates.yml


stages:

  - test

  - build

  - deploy


test:

  extends: .test-template


build:

  extends: .build-template


deploy:

  extends: .deployment-template

That’s it.


No AWS CLI.

No Helm commands.

No Terraform logic.

No secrets.


From a dev team’s perspective, this is perfect:


“We write code.

We commit.

The pipeline just works.”





Layer 2: The Central CI/CD Repo (The Spine)



This is where DevOps actually lives.


It contains three things.





1) Job Templates (YAML = Structure)


.build-template:

  stage: build

  script:

    - chmod +x scripts/build_scripts.sh

    - scripts/build_scripts.sh

This defines:


  • When the job runs

  • What it calls

  • What artifacts it emits



It does not define how building works.





2) Bootstrap Defaults (YAML = Loader)


default:

  before_script:

    - mkdir -p $CI_PROJECT_DIR/scripts

    - curl ... build_scripts.sh -o scripts/build_scripts.sh

    - curl ... deployment_scripts.sh -o scripts/deployment_scripts.sh

    - chmod +x scripts/*.sh

Every pipeline:


  • Pulls the real scripts at runtime

  • From a central repo

  • Using an API token stored in CI variables



This gives you:


  • Central control

  • Zero duplication

  • One place to patch behavior






3) Runtime Scripts (Shell = Behavior)



This is where real work happens:


  • Installing tools

  • Building artifacts

  • Running tests

  • Deploying to Kubernetes

  • Running Terraform

  • Handling rollbacks



These scripts are:


  • Versioned

  • Reviewable

  • Testable

  • Patchable



And most importantly:


They are not buried inside YAML.





Layer 3: Environment Resolution (The Missing Contract)



Most DevOps systems fail here.


Environments are usually:


  • Implicit

  • Tribal

  • Undocumented



That’s how prod gets broken.





The Minimal 3-Variable Environment Contract



You only need three variables to make dev autonomous and prod safe.

SCRIPT_BRANCH   → which version of the scripts to run

ENV_TIER        → what rules apply

TARGET_CLUSTER  → where deployments go


Dev:


SCRIPT_BRANCH=dev

ENV_TIER=dev

TARGET_CLUSTER=dev


Prod:


SCRIPT_BRANCH=main

ENV_TIER=prod

TARGET_CLUSTER=prod





How Scripts Use This


if [ "$ENV_TIER" = "prod" ]; then

  echo "Direct prod deploys are not allowed"

  exit 1

fi

case "$TARGET_CLUSTER" in

  dev)  export KUBECONFIG=dev.kubeconfig ;;

  prod) export KUBECONFIG=prod.kubeconfig ;;

esac

This gives you:


  • Behavioral isolation

  • Logical isolation

  • Physical isolation



With three variables.





What Dev Teams Get (And Why This Feels Amazing)



From a dev team’s point of view:



✅ Real Autonomy



They can:


  • Build artifacts

  • Run tests

  • Deploy to dev Kubernetes

  • Change dev behavior

  • Debug failures



Without:


  • Touching prod credentials

  • Touching prod clusters

  • Touching platform YAML






✅ A Pipeline That’s Predictable



When something fails:


  • YAML shows what ran

  • Scripts show how it ran

  • Variables show where it ran



That’s debuggable.





✅ Zero DevOps Yak-Shaving



They never need to:


  • Install kubectl locally

  • Learn Helm internals

  • Understand GitLab APIs

  • Manage secrets



They just write code.





Why This Architecture Works in Real Life




1) It Centralizes Risk



  • Tool upgrades → one repo

  • Security patches → one repo

  • Pipeline changes → one repo






2) It Makes Behavior Deterministic



Every environment is defined by:

Scripts + Variables + Templates

Not by tribal knowledge.





3) It Scales Across Teams



Adding a new team means:


  • Create repo

  • Add .gitlab-ci.yml

  • Set three variables



Done.





The Honest Part: This Stuff Is Hard



Yes — pipelines will fail.


Yes — scripts will break.


Yes — YAML will betray you.


But here’s the difference:


When something breaks, you know where to look.


That alone puts you ahead of most DevOps implementations.





Final Thought: DevOps Is a Product



The biggest shift is this:


Your CI/CD system is not glue code.

It is a software product.


It needs:


  • Architecture

  • Versioning

  • Contracts

  • Environments

  • Ownership

  • Guardrails



When you treat it that way, DevOps stops being chaos

and starts being leverage.





About Learn, Teach, Master



Learn, Teach, Master exists to capture real engineering knowledge

that actually works in production.


No buzzwords.

No hype.

No vendor propaganda.


Just reality.





Optional Call-Out Box for the Article



The Mickey Mouse Rule


If you can’t draw your DevOps system as three circles

(App Repo, CI/CD Repo, Environment)

you don’t actually understand it yet.




Master DevOps piece.

 
 
 

Recent Posts

See All

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
Post: Blog2_Post

Subscribe Form

Thanks for submitting!

©2020 by LearnTeachMaster DevOps. Proudly created with Wix.com

bottom of page