LLMOpsThe LLMOps lifecycle · MLflow 3 · FastAPI · Docker · AWS/Azure
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
41 small wins to finish your pathNext lesson →

CI/CD for an LLM app

CI/CD for an LLM app is a pipeline that runs on every push: it lints the code, runs the tests, runs an evaluation set as a gate, builds the container and deploys, so a change ships only when the quality check passes.

Last updated: 15 Oct, 2026 · LLMOps

The The Azure deployment from the project lesson was the last of the where-to-deploy choices. This lesson is how a deploy happens without a person running commands by hand. The pattern is the one used across the MLOps work, carried into the Detailed LLMOps Project Lifecycle video's deployment stage: the steps that build and ship are automated, and the step that makes an LLM pipeline different is an evaluation gate between the tests and the deploy. It is shown as a GitHub Actions workflow, not run, because it runs on a push to a repository.

A workflow that gates the deploy on an eval

The workflow triggers on a push to main and runs one job of ordered steps. The lint and the unit tests are the usual CI; the step that matters for an LLM app is the evaluation run, placed before the build so a drop in answer quality fails the job and the deploy steps never run.

yaml
name: deploy
on:
  push:
    branches: [main]

jobs:
  ship:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "3.11" }
      - run: pip install -r requirements.txt
      - run: ruff check .            # lint the code
      - run: pytest tests/eval       # the eval gate: fails the job if a score drops
      - run: docker build -t shop-assistant .
      - run: ./deploy.sh             # deploy, reached only when the eval passed

Why the eval is a gate, not a report

A unit test checks that the code runs; it cannot tell you the model's answers got worse after a prompt edit or a model swap. The evaluation set can, and making it a step that fails the job turns it from a report someone might read into a gate a bad change cannot pass. A cheaper model or a trimmed prompt from the cost lesson reaches production only after it clears this bar.

  • Lint and unit tests catch a broken build and a code error, the same as any app's CI.
  • The evaluation gate runs your scored examples and fails the job if the score falls below a threshold, so a quality regression blocks the deploy.
  • Build and deploy run last, and only when every step before them passed, so nothing ships that did not clear the gate.
A pipeline left to right: push to main, lint which catches a broken build, tests which catch a code error, the evaluation gate in orange which catches a quality drop, build image, and deploy. The gate is labelled as the step a plain app's CI has no equivalent for, and a red arrow drops from it to a box reading score below the threshold, the job fails and nothing is built or deployed. A panel underneath notes that an eval gate is only as honest as the examples behind it, and that a model call inside CI costs money and varies run to run.

Code CI against an LLM app's CI

StepA plain app's CIAn LLM app's CI
LintYesYes
Unit testsCode correctnessCode correctness
Evaluation gateNot applicableScores answers, fails on a drop
BuildThe artifact or imageThe container image
DeployOn greenOn green, including the eval

Where a CI/CD gate helps

  • A prompt or model change, where the eval gate catches a quality drop that no unit test would see.
  • A team shipping often, where automating build and deploy removes the manual step a person forgets.
  • A regression guard, where the scored set grows with every bug found, so the same bug cannot ship twice.
Watch out. An eval gate is only as honest as the examples behind it, and a model call inside CI costs money and varies run to run. Keep the gated set small, graded and deterministic where you can, and run heavier judge-model evaluations on a schedule rather than on every push, so the gate stays fast and its pass or fail means something.
Try it yourself
  • Write a minimal GitHub Actions workflow that runs pytest on a push and read the run in the Actions tab.
  • Add a step that runs five scored examples and fails the job when the average score drops below a line you set.
  • Move the build and deploy steps after the eval step and confirm a failing eval stops the deploy.

Every expert started right here.