Referensi cepat GitLab CI/CD. Pipeline YAML, stages, jobs, runners, cache, artifacts, environments, dan security scanning. Perfect buat DevOps engineer.
Pipeline GitLab CI/CD didefinisikan di file .gitlab-ci.yml di root repository. File ini berisi jobs yang dikelompokkan ke dalam stages, dan setiap job dieksekusi oleh runner. Pipeline baru dibuat setiap kali kamu push kode atau buka merge request.
# .gitlab-ci.yml
stages:
- build
- test
- deploy
build-app:
stage: build
script:
- echo "Building $CI_PROJECT_NAME"
- make build
unit-test:
stage: test
script:
- make testKonsep intinya begini: job adalah unit kerja terkecil (satu eksekusi script di satu runner), stage adalah grup dari jobs. Pipeline berjalan per commit, dan hasilnya bisa dilihat di tab Build > Pipelines di UI GitLab.
Stages dijalankan berurutan sesuai urutan di daftar. Semua jobs dalam satu stage berjalan paralel. Kalau satu stage gagal, stage berikutnya tidak akan jalan, kecuali job yang gagal punya allow_failure: true.
stages:
- build
- test
- deploy
# Stage khusus yang selalu tersedia
prepare:
stage: .pre # selalu jalan paling awal
script: echo "Prepare"
cleanup:
stage: .post # selalu jalan paling akhir
script: echo "Cleanup".pre dan .post tidak perlu dideklarasikan di daftar stages, keduanya sudah tersedia otomatis.stages, semua job default masuk ke stage test.Satu job punya banyak keyword yang mengatur cara dia berjalan. Ini template job yang memakai keyword paling sering dipakai:
unit-test:
stage: test
image: node:22
tags: [docker]
before_script:
- npm ci
script:
- npm test
after_script:
- echo "Test selesai"
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'
timeout: 10m
retry: 1
interruptible: trueTabel referensi keyword yang paling penting:
| Keyword | Fungsi |
|---|---|
script | Perintah shell yang dijalankan, wajib ada |
before_script | Perintah persiapan sebelum script utama |
after_script | Perintah penutup, jalan bahkan setelah job gagal |
stage | Nama stage tempat job ini berada |
image | Container image yang dipakai job (executor Docker) |
services | Container pendukung, misalnya database |
tags | Memilih runner sesuai tag |
rules | Kondisi kapan job masuk pipeline (pengganti only/except) |
when | on_success, on_failure, always, manual, atau delayed |
allow_failure | Job boleh gagal tanpa mematikan pipeline |
needs | Menyusun DAG antar jobs lintas stage |
environment | Mengaitkan job dengan deployment environment |
artifacts | File yang dihasilkan dan dibagikan |
cache | File yang disimpan antar pipeline untuk mempercepat job |
resource_group | Membatasi concurrency, misalnya untuk deploy |
retry | Jumlah percobaan ulang saat job gagal |
timeout | Batas waktu job sebelum dibatalkan |
rules menggantikan only/except yang sudah legacy. Kombinasi paling umum: jalan di merge request dan di branch utama.
# Workflow level: kontrol pipeline dibuat atau tidak
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_TAG'
# Job level
deploy:
script: ./deploy.sh
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual# Hanya saat file tertentu berubah
docker-build:
script: docker build -t app .
rules:
- changes:
- Dockerfile
- src/**/*
# Delayed deploy setelah 5 menit
rollout:
script: ./rollout.sh
when: delayed
start_in: 5 minutesUntuk pipeline terjadwal, pakai schedules di UI (Build > Pipeline schedules) dengan cron syntax. Job bisa memfilter dengan $CI_PIPELINE_SOURCE == "schedule". Trigger pipeline dari job lain (downstream atau parent-child) memakai keyword trigger:
trigger-child:
trigger:
include:
- local: child-pipeline.yml
strategy: dependRunner adalah proses yang mengeksekusi jobs. Ada beberapa jenisnya, dan memilih yang tepat menentukan kecepatan plus keamanan pipelinemu.
# Job dengan tags tertentu hanya jalan di runner yang punya tag sama
build-linux:
tags: [linux, docker]
script: make build# Registrasi self-hosted runner (gitlab-runner harus terinstall dulu)
gitlab-runner register \
--url https://gitlab.com \
--token glrt-xxxxxxxxxxxx \
--executor docker \
--docker-image node:22Executor yang sering dipakai: docker (job jalan di container, paling umum), shell (job jalan langsung di host runner), dan kubernetes (job jalan sebagai Pod di cluster). Executor shell paling gampang bocor antar job, jadi hindari buat proyek publik.
Job dengan executor Docker jalan di dalam container image. services menambahkan container pendukung yang bisa diakses lewat network alias.
integration-test:
image: node:22-alpine
services:
- name: postgres:16
alias: db
- name: redis:7
alias: cache
variables:
DATABASE_URL: postgres://postgres:postgres@db:5432/app_test
REDIS_URL: redis://cache:6379
script:
- npm run test:integrationVariabel FF_NETWORK_PER_BUILD bikin tiap job dapat network terisolasi, jadi container job dan services saling terlihat tapi terpisah dari job lain.
Cache menyimpan dependency antar pipeline biar tidak download ulang terus. Kuncinya di cache key: kalau key sama, cache lama dipakai lagi.
npm-cache:
stage: build
image: node:22
cache:
key:
files:
- package-lock.json
prefix: node
paths:
- node_modules/
policy: pull-push
script:
- npm ci
- npm run buildpolicy: pull hanya mengambil cache (job read-only, hemat bandwidth).policy: push hanya membuat cache.policy: pull-push default, ambil lalu simpan lagi kalau berubah.files otomatis berubah saat lockfile berubah, jadi cache stale tidak kepakai.Artifacts adalah file hasil job yang diupload ke GitLab dan bisa diunduh job berikutnya. Bedanya dengan cache: artifacts untuk output build, cache untuk dependency.
build:
stage: build
script: npm run build
artifacts:
paths:
- dist/
exclude:
- dist/**/*.map
expire_in: 1 week
when: on_success
reports:
junit: reports/junit.xml
deploy:
stage: deploy
script: ./deploy.sh dist/
dependencies:
- build # hanya ambil artifacts dari job buildexpire_in mengatur umur artifacts (default 30 hari). never bikin artifacts permanen.dependencies: [] bikin job tidak mengunduh artifacts sama sekali, berguna untuk job deploy yang ringan.artifacts:when: on_failure menyimpan file meski job gagal, berguna untuk log dump.reports yang sering dipakai: junit, coverage_report, dotenv, container_scanning, sast, dependency_scanning, secret_detection.Secara default job menunggu stage sebelumnya selesai semua. Keyword needs memutus ketergantungan itu jadi graf (DAG), jadi job bisa jalan lebih cepat.
build-api:
stage: build
script: make build-api
build-web:
stage: build
script: make build-web
test-api:
stage: test
needs: [build-api]
script: make test-api
test-web:
stage: test
needs: [build-web]
script: make test-web
deploy:
stage: deploy
needs: [test-api, test-web]
script: make deployDi contoh ini test-web tidak menunggu build-api, hanya build-web. Job dengan needs hanya mengunduh artifacts dari jobs yang dia butuhkan, jadi pipeline jadi lebih ramping. Tambahkan needs: [] kalau job mau jalan langsung tanpa menunggu apa pun.
variables:
DEPLOY_ENV: "staging"
APP_URL: "https://app.example.com"
print-vars:
script:
- echo "Deploy ke $DEPLOY_ENV"
- echo "Commit $CI_COMMIT_SHORT_SHA"Predefined variables yang paling sering dipakai: CI_COMMIT_SHA, CI_COMMIT_BRANCH, CI_COMMIT_REF_SLUG, CI_COMMIT_TAG, CI_PIPELINE_SOURCE, CI_PROJECT_DIR, CI_JOB_TOKEN, CI_ENVIRONMENT_NAME.
# Ambil nilai secret dari UI (Settings > CI/CD > Variables)
deploy:
script:
- ./deploy.sh --token "$DEPLOY_TOKEN"
environment:
name: productionAturan main variables:
CI_JOB_TOKEN otomatis tersedia tiap job, bisa dipakai untuk clone repo lain atau pull dari package registry milik grupmu sendiri.Environment adalah record tempat job deploy berjalan. Kamu mendapat histori deployment, tombol rollback, dan URL aplikasi langsung dari UI.
deploy-staging:
stage: deploy
script: ./deploy.sh staging
environment:
name: staging
url: https://staging.example.com
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
deploy-production:
stage: deploy
script: ./deploy.sh production
environment:
name: production
url: https://example.com
deployment_tier: production
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manualdeployment_tier menerima nilai production, staging, testing, development, dan other. Tier ini dipakai untuk grouping plus protected environments.
Environment bisa dinamis per branch, ini basis fitur review apps:
review:
script: ./deploy-preview.sh
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://$CI_COMMIT_REF_SLUG.preview.example.com
on_stop: stop-review
stop-review:
script: ./teardown-preview.sh
when: manual
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stopon_stop merujuk job pembersih yang dijalankan saat environment dihentikan, biasanya saat branch dihapus.
Environment seperti production bisa dikunci supaya hanya role atau user tertentu yang boleh deploy (fitur Premium ke atas). Konfigurasinya ada di Settings > CI/CD > Protected environments. Kamu bisa batasi berdasarkan role (Maintainers, Developers), user spesifik, atau group, dan juga via API protected_environments.
GitLab menyediakan template security scanning yang tinggal di-include. Hasil scan masuk sebagai artifact report lalu muncul di merge request widget dan security dashboard.
include:
- template: Jobs/SAST.gitlab-ci.yml
- template: Secret-Detection.gitlab-ci.yml
- template: Container-Scanning.gitlab-ci.yml
- template: Dependency-Scanning.gitlab-ci.yml
container_scanning:
variables:
CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHAPerbandingan jenis scan:
| Scan | Target | Yang dideteksi |
|---|---|---|
| SAST | Source code | Kerentanan di kode (injection, XSS, dsb.) |
| Secret detection | Isi repo | API key, token, password yang tercommit |
| Dependency scanning | Manifest dependency (lockfile) | CVE di package pihak ketiga |
| Container scanning | Image di registry | CVE di base image dan layer |
| DAST | Aplikasi yang berjalan | Kerentanan runtime (misal OWASP Top 10) |
| IaC scanning | Terraform, Kubernetes manifest | Misconfig infrastruktur |
Catatan penting soal lisensi: SAST dan secret detection punya versi dasar di tier gratis, sedangkan dependency scanning dan fitur lanjutan seperti vulnerability dashboard penuh membutuhkan tier Ultimate. Cek halaman docs tiap scanner untuk status tier terbaru karena sering berubah.
Untuk menegakkan scan lintas proyek, pakai scan execution policies di level group. Policy bisa memaksa SAST, secret detection, dan container scanning jalan di setiap pipeline branch utama tanpa tim proyek bisa mematikannya.
# Contoh policy (disimpan di security policy project)
scan_execution_policy:
- name: Wajibkan scan di main
enabled: true
rules:
- type: pipeline
branches: [main]
actions:
- scan: sast
- scan: secret_detectionPipeline besar sebaiknya dipecah dan dipakai ulang. Keyword include mendukung beberapa sumber:
include:
- local: '/templates/.deploy-template.yml'
- project: 'my-group/ci-templates'
ref: v2.3.0
file: '/node.yml'
- remote: 'https://gitlab.com/example/ci/raw/main/lint.yml'
- component: '$CI_SERVER_FQDN/my-group/ci-templates/deploy@1.0'Untuk job parsial yang sering diwariskan, pakai hidden job (diawali titik) plus extends dan !reference:
.node-base:
image: node:22
before_script:
- npm ci
build:
extends: .node-base
script:
- npm run build
test:
extends: .node-base
script:
- !reference [.node-base, before_script]
- npm testdebug-job:
variables:
CI_DEBUG_TRACE: "true" # verbose logging runner
script:
- echo "Pipeline $CI_PIPELINE_ID job $CI_JOB_ID"
- env | sort | grep -v TOKENexpire_in atau hapus dependencies ke job itu. Pesan errornya "could not retrieve the needed artifacts".resource_group: production di job deploy mencegah dua deploy berjalan bersamaan.interruptible: true di job awal membuat pipeline lama otomatis dibatalkan saat push baru datang, hemat runner.node:22.11 bukan latest) supaya build reproduciblerules daripada only/except yang sudah legacytimeout di setiap job, default bisa terlalu panjangexpire_in wajarwhen: manual plus protected environmentinclude dan reusable componentsneeds untuk mempercepat pipeline panjang| Istilah | Arti |
|---|---|
| Pipeline | Rangkaian jobs yang dibuat untuk satu commit atau event |
| Job | Unit eksekusi terkecil, satu script di satu runner |
| Stage | Grup jobs yang berjalan paralel, dieksekusi berurutan antar stage |
| Runner | Agen yang mengeksekusi jobs, bisa shared atau self-hosted |
| Executor | Cara runner menjalankan job: docker, shell, kubernetes |
| Artifact | File output job yang diunggah ke GitLab dan dibagikan |
| Cache | File dependency yang disimpan antar pipeline |
| DAG | Directed acyclic graph, ketergantungan jobs via needs |
| Environment | Record tujuan deploy dengan histori dan URL |
| Deployment | Satu kejadian deploy ke sebuah environment |
| Review app | Environment dinamis per branch untuk preview |
| SAST | Static application security testing, scan kode |
| DAST | Dynamic application security testing, scan aplikasi hidup |
| Merge train | Antrean merge request yang digabung satu per satu |
| CI_JOB_TOKEN | Token sementara otomatis untuk autentikasi antar repo |
Login atau daftar akun gratis untuk membaca cheat sheet ini.