
Citadel Cloud Management
GitLab CI/CD Pipeline Templates
DevOps PipelinesCreated by Kenny Ogunlowo
Product Description
GitLab CI/CD Pipeline Templates
GitLab CI has a unique advantage over GitHub Actions: the runner infrastructure is yours. But that advantage becomes a liability when the team treats runners as cattle they never monitor. At an energy sector client, a shared GitLab runner had 3GB of Docker images from 2019 filling its disk. Every pipeline spent 4 minutes in docker pull because the cache was corrupted. Nobody investigated because "pipelines are just slow." This template includes runner health monitoring and cache management that prevents that decay.
This .gitlab-ci.yml implements a multi-stage pipeline with DAG dependencies, environment promotion, and security scanning that I have deployed for teams processing sensitive infrastructure data.
Pipeline Stages
-
stages: [lint, test, security, build, deploy-dev, deploy-staging, deploy-prod] — DAG dependencies via
needs:keywords allow parallel execution where stages are independent. Lint and security run simultaneously. -
lint —
image: golangci/golangci-lint:v1.57or language-equivalent. Runs in under 60 seconds. Cache:$CI_COMMIT_REF_SLUGkeyed. -
test — Parallel jobs via
parallel: 4with test splitting.services: [postgres:16, redis:7]for integration tests. Coverage extracted via regex and displayed in MR widget. -
security —
include: Security/SAST.gitlab-ci.ymlandSecurity/Secret-Detection.gitlab-ci.ymlfrom GitLab templates. Container scanning viaSecurity/Container-Scanning.gitlab-ci.yml. Results appear in the MR security widget. -
build —
docker buildwith Kaniko (gcr.io/kaniko-project/executor:v1.22.0) for rootless builds in shared runners. Push to GitLab Container Registry with$CI_COMMIT_SHAtag. -
deploy-dev —
environment: devwithauto_stop_in: 1 week. Deploys via Helm to the dev cluster. Runsonly: [develop]. -
deploy-staging —
environment: stagingwithwhen: manual. Requires MR approval before deploy button is clickable. Runs integration test suite post-deploy. -
deploy-prod —
environment: productionwithwhen: manualandallow_failure: false. Protected environment requiring two approvals. Canary deployment withkubectl set imageat 10% weight.
Security Gates
- GitLab SAST — Built-in analyzers for 15+ languages. Runs automatically via template inclusion. Findings block MR merge when severity is CRITICAL.
- Secret Detection — Scans for API keys, tokens, and credentials in code and commit history. Pre-receive hook blocks pushes containing detected secrets.
- Container Scanning — Trivy-based scanner runs against built images. Results integrated into GitLab's vulnerability dashboard.
-
License Compliance —
Security/License-Scanning.gitlab-ci.ymlchecks dependencies against approved license policies.
What Breaks First
-
Runner disk full from Docker layers — Shared runners accumulate Docker images and build caches. Fix: schedule
docker system prune -af --filter "until=48h"as a cron job on every runner. -
Cache key collision between branches —
cache: key: $CI_COMMIT_REF_SLUGmeans branches with similar names share caches. Fix: include$CI_JOB_NAMEin the cache key. -
Kaniko context size timeout — Large repositories with node_modules or vendor directories cause Kaniko to timeout building the context. Fix: add a
.dockerignorethat excludes everything except the build output and required files.