AI EngineeringZero to ProductionHome·About·What’s new·Contact
GitLab CI/CD with AI · Part 1

GitLab CI/CD & Where AI Fits

Before you can automate a pipeline with an LLM, you need the pipeline. This chapter is the foundation of the track: how GitLab CI/CD actually works — .gitlab-ci.yml, stages, jobs, runners, merge-request pipelines — and the three distinct places an AI model plugs in. Everything after this builds on these pieces.

⏱️ ~1.5 hours🦊 GitLab CI/CD🎯 Beginner→Tech-lead

Learning objectives

  • Explain the GitLab CI/CD model: pipelines, stages, jobs, and runners.
  • Read and write a basic .gitlab-ci.yml.
  • Understand merge-request pipelines — where AI review and automation hook in.
  • Name the three places an LLM fits into a pipeline, with either Claude or OpenAI.
This track's code runs in GitLab CI, not the in-browser terminal — the jobs need network access, repository context, and API keys that only exist in a real CI environment. Read and adapt the examples into your own project; they're complete and correct, but there's nothing to "run" on this page.

1 · The GitLab CI/CD model essential

Strip away the jargon and CI/CD is one idea: every time you push code, a machine runs a checklist for you. Does it build? Do the tests pass? Is it safe to merge? GitLab CI/CD automates that checklist so a human doesn't run it by hand (and doesn't forget). The whole system is driven by a single file in your repo root — .gitlab-ci.yml — which GitLab reads on every push to decide what to run.

Four nouns carry the whole model. A pipeline is one full run of your checklist, triggered by a push or a merge request. It's divided into stages that run in order (typically build → test → deploy). Each stage holds one or more jobs — the actual commands — and jobs in the same stage run in parallel, while stages run sequentially. Jobs execute on a runner: a machine (GitLab-hosted or your own) that checks out your code and runs the job's script in a container. That's the entire mental model; everything else is detail on top of it.

The common mistake coming in is imagining CI as "a script that runs somewhere." It's more structured than that: the stage/job split is what gives you parallelism and ordering, and the runner-in-a-container model is why a job starts from a clean checkout every time (no leftover state from the last run). Hold the pipeline → stages → jobs → runner picture and GitLab CI stops being a wall of YAML.

push / MR → pipeline → stages (in order) → jobs (parallel) on runners build compile test unit lint 🤖 AI review job deploy release on a runner stages run in order; jobs in a stage run in parallel Pipeline → stages → jobs → runner. A push or MR triggers a pipeline; stages run in sequence (build, test, deploy); jobs within a stage run in parallel on runners. An AI review is just another job in the test stage.
🗺️ How to read this diagram
  • The three big boxes are stages — they run strictly left to right: build, then test, then deploy.
  • The small green boxes inside are jobs; those in the same stage run in parallel (unit + lint together).
  • The amber box is the point of this whole track: an AI review job is just another job in the test stage — nothing special structurally.
  • Everything runs on a runner — a fresh container that checks out your code per job.

In short: stages order the work, jobs parallelize it, runners execute it — and an LLM call is just a job's script.

2 · Reading a .gitlab-ci.yml essential

The config is YAML. Each top-level key (that isn't a reserved word) is a job; stages declares the order; each job names its stage and a script of shell commands. Here's a minimal, complete pipeline.

Lab G1.1
.gitlab-ci.ymlstages:
  - build
  - test

build-app:
  stage: build
  script:
    - echo "Compiling..."
    - make build

run-tests:
  stage: test
  script:
    - pip install -r requirements.txt
    - pytest -q
▶ How this works
  1. stages: lists the order — build runs fully before test starts.
  2. build-app and run-tests are jobs (the top-level names); each declares which stage it belongs to.
  3. Each job's script is just shell commands run on a fresh runner — so pytest runs against a clean checkout of your code.

Try this: add a third stage deploy with a job that only runs on the default branch (you'll add the rules: for that in gl3) — the skeleton is always stages + jobs + scripts.

Jobs are just shellA job's script is ordinary shell on a container. That's the key that unlocks this whole track: if you can call an LLM from a Python script on your laptop, you can call it from a CI job — same code, now triggered by a push instead of by you.

3 · Merge-request pipelines intermediate

The merge request is where AI automation earns its keep, so it's worth understanding precisely. A merge request (MR) is GitLab's proposal to merge one branch into another — the equivalent of a GitHub pull request. GitLab can run a special merge-request pipeline that fires when an MR is opened or updated, and crucially these pipelines have access to the diff — exactly what changed — plus the MR's metadata (title, description, author).

That diff is the raw material for AI review (gl2): a job can grab the changes, hand them to a model, and post the model's feedback back onto the MR as a comment. You scope a job to MR pipelines with the rules: keyword and the predefined $CI_PIPELINE_SOURCE variable, so the AI review runs only on merge requests, not on every push.

Lab G1.2
.gitlab-ci.ymlai-review:
  stage: test
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'   # MRs only
  script:
    - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
    - git diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME > changes.diff
    - python review.py changes.diff          # calls the model — gl2
▶ How this works
  1. rules: with $CI_PIPELINE_SOURCE == "merge_request_event" makes this job run only in MR pipelines — not on branch pushes.
  2. The script captures the diff against the target branch into changes.diff using GitLab's predefined MR variables.
  3. python review.py changes.diff is where the LLM comes in — that script (built in gl2) sends the diff to Claude or OpenAI and posts the review back.

Try this: GitLab exposes many predefined variables ($CI_MERGE_REQUEST_IID, $CI_PROJECT_ID, $CI_COMMIT_SHA). They're how a job knows which MR it's reviewing — you'll use them to post comments back in gl2.

4 · The three places AI fits advanced

Across this whole track, an LLM plugs into GitLab in exactly three ways — worth naming now so the later chapters slot into place. (1) Review: a job reads the MR diff and posts feedback (gl2). (2) Generation / action: a job calls a model to produce something — a changelog, release notes, a test, a summary — and commits it or attaches it (gl3). (3) Routing: when you use more than one model, a job decides which model handles a given task, with fallback if one fails (gl4). All three are "a job whose script calls an LLM API" — the structure you already know.

And a fourth option that isn't your code at all: GitLab Duo, GitLab's built-in AI features (code suggestions, chat, MR summaries) that run as a managed product rather than jobs you write. The track's framing (expanded in gl3): reach for Duo when its built-in features fit, and write your own API-calling jobs when you need control, a specific model, or logic Duo doesn't offer.

Why dual-vendor from the startEvery code example in this track shows Claude and OpenAI side by side on a toggle, because a CI pipeline is exactly where you want vendor flexibility: route reasoning-heavy review to one model, cheap generation to another, and keep a fallback if a provider has an outage (gl4). The pipeline is vendor-agnostic by design.

5 · Tech-lead — CI as the enforcement point tech-lead

The reason to put AI in the pipeline rather than in each developer's editor is consistency: a CI job runs the same way for everyone, every time, and can be made a required check before merge. That makes the pipeline the natural enforcement point for AI-assisted quality — an AI review that every MR gets, a generated changelog that's never forgotten, a security scan that can't be skipped. The lead-level principle: editor AI assists the individual; pipeline AI enforces the standard. This track builds the pipeline kind.

🪜 Practice ladder beginner → industry

  1. Beginner: write a two-stage .gitlab-ci.yml (build, test) with one job each.
  2. Easy: add a job scoped to MRs only with rules: $CI_PIPELINE_SOURCE.
  3. Core: capture the MR diff to a file in a job script.
  4. Stretch: list which predefined CI variables you'd need to post a comment back to an MR.
  5. Hard: sketch the three AI insertion points for a repo you know (review / generate / route).
  6. Industry: decide which AI checks should be required before merge vs advisory, and why.

✓ Checkpoint — you can move on when you can…

  • Explain pipelines, stages, jobs, and runners.
  • Read and write a basic .gitlab-ci.yml.
  • Scope a job to merge-request pipelines and grab the diff.
  • Name the three places an LLM fits into a pipeline.

Knowledge check check yourself

✓ Knowledge check

In GitLab CI, what's the relationship between pipelines, stages, jobs, and runners?

Show answer
A pipeline is one full run triggered by a push or merge request. It's divided into stages that run in sequence (e.g. build → test → deploy). Each stage contains jobs (the actual command scripts), and jobs in the same stage run in parallel. Every job executes on a runner — a machine/container that checks out the code fresh and runs the job's script. It's all declared in .gitlab-ci.yml.
✓ Knowledge check

How do you make a job run only on merge requests, and why does that matter for AI review?

Show answer
Use rules: with if: '$CI_PIPELINE_SOURCE == "merge_request_event"' so the job runs only in merge-request pipelines, not on every branch push. It matters because MR pipelines have access to the diff and MR metadata — exactly what an AI review job needs to read the changes and post feedback back onto the specific merge request.
© 2026 studybydoing.in · AI Engineering: Zero to Production · All rights reserved. · About · Privacy Policy · Terms · Contact
Educational content, provided as-is and without warranty. Code samples are examples — review, test, and adapt them before using in production. See the Terms of Use & Disclaimer. Use at your own risk.
© studybydoing.in