Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for GitLab CI/CD By James Joyner IV · · 10 min read

Customizing GitLab Auto DevOps Without Fighting It

Auto DevOps gets you to a deploy in minutes, then fights you for months. Here is how I override just the parts I need and use AI to decode the hidden template.

  • #gitlab
  • #ci-cd
  • #auto-devops
  • #ai

The first time I enabled Auto DevOps on a real project, I had a running deployment in about eight minutes and felt like a genius. The second week I needed to change one thing in the build stage and discovered the entire pipeline came from a template I couldn’t see, full of jobs I didn’t write. That gap — between “magic that works” and “magic I can edit” — is where most teams either abandon Auto DevOps or learn to bend it. This is the bending guide.

What Auto DevOps actually is

Auto DevOps is a single hidden include that pulls in a large bundle of jobs: build, test, code quality, SAST, dependency scanning, container scanning, and deploy-to-Kubernetes. When you toggle it on in Settings, GitLab silently prepends this to your pipeline:

include:
  - template: Auto-DevOps.gitlab-ci.yml

That is the key insight. It is just an include. Which means everything you know about include, extends, and variable precedence still applies. You are not trapped; you just can’t see the source until you go look at it.

See the template before you touch it

You cannot override what you can’t read. The Auto-DevOps template lives in the GitLab codebase under lib/gitlab/ci/templates/. Pull it up, and feed it to an AI assistant with a direct question: “This is the Auto DevOps template. List every job it defines, which stage each belongs to, and which CI/CD variables change its behavior.” AI is genuinely strong at summarizing a large, dense YAML file into a map you can navigate. I do this first, every time, before changing anything.

Pro Tip: Ask the AI specifically for the variables that toggle behavior. Auto DevOps is configured almost entirely through CI/CD variables like AUTO_DEVOPS_PLATFORM_TARGET, POSTGRES_ENABLED, and TEST_DISABLED. Most “customization” is setting a variable, not editing YAML.

Override by variable first

The cleanest customization is no YAML at all. Disable the bundled Postgres you don’t need:

variables:
  POSTGRES_ENABLED: "false"
  CODE_QUALITY_DISABLED: "true"
  AUTO_DEVOPS_DEPLOY_DEBUG: "1"

These go in .gitlab-ci.yml or in project CI/CD settings. Reach for variables before you reach for job overrides, because variables survive template upgrades and job overrides can silently break when GitLab changes the underlying job.

Override a single job with extends. When a variable isn’t enough — say you need a custom build that does multi-stage caching — you override the specific job by name. Because the template is included first, your definition with the same job name wins on a per-key basis:

include:
  - template: Auto-DevOps.gitlab-ci.yml

build:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - docker build --cache-from "$CI_REGISTRY_IMAGE:cache" -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
  rules:
    - if: $CI_COMMIT_BRANCH

The risk: you must use the exact job name from the template. Misspell it and you get two jobs, the original plus yours, both running. This is the single most common Auto DevOps mistake I see. Verify the name against the template you read in the previous step.

Inject extra stages and jobs cleanly

Sometimes you don’t want to replace anything — you want to add a step, like a compliance scan, into the existing flow. Declare your stages to slot alongside the Auto DevOps ones:

include:
  - template: Auto-DevOps.gitlab-ci.yml

stages:
  - build
  - test
  - compliance
  - deploy

license-check:
  stage: compliance
  image: alpine:3.20
  script:
    - ./scripts/verify-licenses.sh
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

When you declare stages:, you must include the stages the template relies on, or its jobs lose their place. This is another spot AI will get subtly wrong — it’ll forget a stage the template needs. Cross-check against the job map you built earlier.

Replacing the deploy entirely

The most common reason teams outgrow Auto DevOps is the deploy. The bundled deploy uses GitLab’s Auto Deploy Helm chart, and at some point you want your own Helm chart or a GitOps push instead. Disable the bundled deploy and bring your own:

variables:
  STAGING_ENABLED: "false"
  PRODUCTION_ENABLED: "false"

deploy:
  stage: deploy
  image: alpine/helm:3.15
  script:
    - helm upgrade --install api ./charts/api
        --set image.tag="$CI_COMMIT_SHA"
        --namespace production
  environment:
    name: production
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: manual

At this point you are using Auto DevOps for build/test/scan and your own logic for deploy — a very reasonable middle ground that keeps the free security scanning without the opaque rollout.

Knowing when to graduate, and pinning the version

Auto DevOps is a fantastic on-ramp and a mediocre destination. My rule: when your override block is longer than the value you’re getting from the template, copy the relevant template jobs into your own .gitlab-ci.yml, drop the include, and own your pipeline. The template is open source; there’s nothing stopping you from forking the bits you use.

Until you graduate, pin the template version. One trap that surprises people: by default, Auto DevOps follows the template version that ships with your GitLab instance. When your instance upgrades, the template can change underneath you — new jobs appear, defaults shift, a stage you relied on moves. For a project where stability matters more than getting the latest scanning, pin to an explicit template instead of the latest include:

include:
  - template: "Auto-DevOps.gitlab-ci.yml"

variables:
  AUTO_DEVOPS_DEPLOY_STRATEGY: "manual"
  STAGING_ENABLED: "true"

Better still, if you’ve made meaningful overrides, copy the template at the version you’ve validated into your own .gitlab/ci/auto-devops-pinned.yml and include: local: it. Now upgrades are a deliberate act — you diff the new template against your pinned copy, adopt the changes you want, and re-test — rather than a surprise that breaks Friday’s deploy. This is the same discipline I apply to any shared include: floating refs are convenient until the day they aren’t, and that day always lands at the worst possible time. AI is handy here for diffing two template versions and summarizing what actually changed between them, which turns a scary upgrade into a short review.

Using AI safely through all of this

AI is the fast junior engineer on this task: it reads the giant template faster than you, drafts override jobs in seconds, and explains what POSTGRES_ENABLED does. What it cannot do is guarantee a job name matches the current template version, or know that your cluster uses a different deploy mechanism. So every AI-drafted override gets read before merge, and the job names get checked against the real template.

And the constant rule: never paste your Kubernetes kubeconfig, registry credentials, or KUBE_* deploy variables into a chat window to get help debugging. If a deploy fails, share the log lines and the job YAML, not the secrets. When deploys break in production, a structured runbook beats ad-hoc prompting — our incident response dashboard is set up for that.

I keep my “map this template” and “override this job” prompts in a reusable set; you can find starting points in the prompt library and the deployment-focused prompt packs.

Conclusion

Auto DevOps isn’t a black box — it’s an include you can read, and every customization is either a variable, an extends, or a same-named override. Use AI to map the template and draft the overrides fast, then verify job names and never share deploy secrets. When the overrides outgrow the template, graduate gracefully. More pipeline guides are in the GitLab CI/CD category.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.