CI/CD adalah jalur otomatis yang membawa kodemu dari git push sampai jalan di production: kodenya diambil, dipasang, dicek, dibungkus, lalu dikirim, dengan urutan yang sama setiap kali. Bayangin dapur katering. Setiap ada resep baru, masakannya dicicipi dulu, baru dikemas, baru dikirim ke pelanggan. Masakan yang gagal dicicipi gak pernah dikemas, apalagi dikirim. Kalau kurirnya menunggu tanda tangan kepala dapur sebelum berangkat, itu Continuous Delivery. Kalau kurirnya langsung jalan begitu kemasan siap, itu Continuous Deployment.
🧪 Tebakan cepat: commit
7d03b5fmembuat testGET /catatangagal. Apakah image Docker-nya tetap di-build dan dikirim keweb-1? Tebak dulu, jawabannya ada di bagian "Satu step gagal, sisanya berhenti".
Deploy manual: cara yang sudah kita pakai
Sampai sekarang, deploy catatan-api dikerjakan tangan: build image di laptop, push ke registry, lalu SSH ke web-1 dan menjalankan Compose dengan tag baru.
docker build -t ghcr.io/budi/catatan-api:7d03b5f .
docker push ghcr.io/budi/catatan-api:7d03b5f
ssh deploy@web-1 "cd /srv/catatan-api && IMAGE_TAG=7d03b5f docker compose up -d"
Langkahnya benar, tapi gak ada yang memaksa test jalan dulu. Commit 7d03b5f ("urutkan catatan terbaru dulu") salah ketik nama tabel jadi catatn, dan di laptop kamu lupa menjalankan npm test. Setelah deploy, setiap GET /catatan di production menjawab 500, dan log app berisi:
2026-10-09 10:15:02 ERROR relation "catatn" does not exist
Itulah masalah deploy manual: ada langkah yang bisa terlewat, tiap orang bisa beda caranya, dan bug baru ketahuan setelah pengguna kena.
CI: setiap push dicek otomatis
Continuous Integration (CI) artinya setiap push (atau pull request) membuat sebuah server CI mengambil kodenya dan menjalankan pemeriksaan yang sama: pasang dependency, lint, test. Hasilnya tanda hijau (lulus) atau merah (gagal) di commit itu. Disebut "integration" karena tujuannya menggabungkan kode semua orang ke main sesering mungkin, dan itu aman karena setiap gabungan dicek mesin.
CD: yang lulus dikirim
Setelah CI hijau, sisanya membungkus dan mengirim: build image, push ke registry, deploy ke web-1. Huruf D di CD punya dua arti:
| Continuous Delivery | Continuous Deployment | |
|---|---|---|
| Otomatis sampai | siap deploy, tinggal satu klik | production |
| Deploy ke production | menunggu approval manusia | langsung, tanpa klik |
| Cocok untuk | tim yang mau memilih jam rilis | tim dengan test yang kuat |
Keduanya sama-sama CD. Bedanya cuma satu: ada tombol persetujuan sebelum production atau gak.
Pipeline catatan-api
Rangkaian tahap itu disebut pipeline, dan tiap tahapnya step. Ini pipeline catatan-api di Lab, lima step berurutan:
| # | Nama step | Perintah | Kategori |
|---|---|---|---|
| 1 | Install dependencies | npm ci |
build |
| 2 | Run ESLint | npm run lint |
lint |
| 3 | Run unit tests | npm test |
test |
| 4 | Build Docker image | docker build lalu docker push |
build |
| 5 | Deploy to web-1 | IMAGE_TAG=... docker compose up -d lewat SSH |
deploy |
Kolom kategori dibaca dari kata kunci di nama step, tanpa peduli huruf besar atau kecil, dengan urutan cek tetap:
- ada "build", "compile", atau "install": build
- ada "lint", "format", atau "style": lint
- ada "test", "spec", atau "coverage": test
- ada "deploy", "release", atau "publish": deploy
- selain itu: other, misalnya "Send Slack notification"
Urutannya penting. "Build and test" kena aturan pertama, jadi build. "Run ESLint" jadi lint, karena "eslint" mengandung "lint".
Satu step gagal, sisanya berhenti
Dua commit di-push berurutan lewat pipeline, dengan Continuous Deployment:
| Step | a41c9e2 tambah pencarian catatan |
7d03b5f urutkan catatan terbaru |
|---|---|---|
| Install dependencies | lulus, 18 detik | lulus, 18 detik |
| Run ESLint | lulus, 6 detik | lulus, 6 detik |
| Run unit tests | lulus, 11 detik | gagal, 9 detik |
| Build Docker image | lulus, 42 detik | dilewati |
| Deploy to web-1 | lulus, 15 detik | dilewati |
| Production di web-1 | jadi a41c9e2 |
tetap a41c9e2 |
Begitu satu step gagal, step sesudahnya gak dijalankan. Image dari 7d03b5f gak pernah dibuat, apalagi dikirim. Itu jawaban tebakannya. Pengguna tetap memakai a41c9e2 yang sehat, dan yang dapat kabar merah adalah kamu, bukan mereka. Potongan log step test-nya di GitHub Actions:
FAIL test/catatan.test.js > GET /catatan > mengembalikan daftar catatan
AssertionError: expected 500 to be 200 // Object.is equality
- Expected
+ Received
- 200
+ 500
Test Files 1 failed | 2 passed (3)
Tests 1 failed | 11 passed (12)
Error: Process completed with exit code 1.
Perbaiki typo-nya, push lagi, dan pipeline yang sama membawa perbaikan itu ke production.
Alatnya
Pilihan populer: GitHub Actions (bawaan GitHub, dibahas di pelajaran berikutnya), GitLab CI, Jenkins, dan CircleCI. Semuanya membaca file konfigurasi di repo, jadi pipeline-mu ikut di-review seperti kode. Urutan lint, test, E2E dan branch protection dibahas di pelajaran Testing di CI/CD Pipeline. Cara menjaga secret deploy di pipeline dibahas di CI/CD Pipeline Security.
⚠️ Jebakan yang sering ketemu
- Deploy manual "sekali ini aja". Melewati pipeline berarti melewati test. Jadikan pipeline satu-satunya jalan ke production.
- Hijau dengan test seadanya. Hijau cuma berarti test yang ada lulus. Bagian kode tanpa test tetap bisa membawa bug.
- Pipeline lambat atau test flaky. Lebih dari sekitar 10 menit, orang mulai menghindarinya. Test yang kadang lulus kadang gagal (flaky) membuat tim terbiasa mengabaikan merah.
- Mengecek kata kunci dengan urutan lain. "Build and test" harus jadi build, karena aturan build dicek pertama. Ubah dulu nama step-nya ke huruf kecil dengan
toLowerCase(), supaya "Run ESLint" tetap ketemu "lint".
TL;DR: CI/CD adalah pipeline otomatis dari push sampai production. CI (Continuous Integration): setiap push otomatis di-install, di-lint, dan di-test, hasilnya hijau atau merah. CD punya dua arti: Continuous Delivery (siap deploy, production menunggu approval manual) dan Continuous Deployment (lulus semua langsung ke production). Pipeline catatan-api: install, lint, test, build image, deploy ke web-1, dan begitu satu step gagal, sisanya dilewati, jadi kode yang test-nya merah gak pernah sampai ke pengguna. Kategori step dibaca dari kata kunci dengan urutan tetap: build, lint, test, deploy, selain itu other. Alat populer: GitHub Actions, GitLab CI, Jenkins, CircleCI.