
Hari 58: CI/CD Otomatis untuk Dev, Staging, dan Prod
Quality gate 10 lapis, lalu auto-deploy ke dev, staging, dan prod tanpa klik manual. Ini cara saya merombak CI/CD SecureBank API jadi pipeline rilis yang jujur.
Hari ke-58 dari challenge 60 Days DevSecOps. Setelah lima puluh hari membangun keamanan berlapis, hari ini saya merombak pipeline CI/CD SecureBank API menjadi proses rilis yang benar-benar otomatis dan jujur.
Perjalanan hari ini penuh pembelajaran, mulai dari quality gate, auto-deploy, hingga cara menyelesaikan konflik branch yang tidak boleh sembarangan.
Quality Gate yang Memeriksa Artefak Final
Pipeline CI yang lama sudah menjalankan build, test, secret scan, SCA, SAST, DAST, dan IaC scan. Ada satu yang kurang: pemeriksaan image final yang benar-benar akan dipakai.
Sekarang ada job image-build-and-scan yang membangun Docker image lalu memindainya dengan Trivy:
image-build-and-scan:
needs: [build-and-test, secret-scan, sca-scan, sast-scan, iac-checkov, iac-trivy]
steps:
- run: docker build --tag securebank:ci-${{ github.sha }} securebank-api
- uses: aquasecurity/trivy-action@master
with:
image-ref: securebank:ci-${{ github.sha }}
severity: CRITICAL,HIGH
exit-code: '1'
Hasilnya, jika ada CVE Critical atau High di image, pipeline langsung berhenti. Tidak ada lagi celah "lolos di source code tapi bocor di image".
Gate ini menemukan masalah nyata: Go stdlib di image mengandung CVE. Solusinya mengubah builder menjadi golang:1.26.6-alpine untuk menutup CVE-2026-39821 dan CVE-2026-46600.
Auto-Deploy Tanpa Klik dan Tanpa Approval
Pola yang saya pakai sebelumnya adalah workflow_dispatch dengan approval environment. Untuk project solo, approval environment justru menambah friction: setiap tahap harus diklik dan di-approve oleh orang yang sama.
Keputusan saya: pindahkan approval ke lapisan PR, lalu biarkan CD berjalan otomatis setelah CI sukses.
.github/workflows/cd-deploy.yml sekarang memakai workflow_run:
on:
workflow_run:
workflows: ["SecureBank CI"]
types: [completed]
branches: [develop, staging, main]
CD hanya berjalan jika CI sukses:
if: github.event.workflow_run.conclusion == 'success'
Job deployment memilih environment dari branch yang memicu CI:
| CI pada branch | Deployment |
|---|---|
develop |
dev |
staging |
staging |
main |
prod + post-deployment verification |
Jadi alurnya sekarang:
merge PR ke develop → CI sukses → auto deploy dev
merge PR ke staging → CI sukses → auto deploy staging
merge PR ke main → CI sukses → auto deploy prod
Tidak perlu klik Run workflow. Tidak perlu approval environment. Yang menjadi gate adalah PR dan CI.
Validasi Manifest Tanpa Cluster
GitHub-hosted runner tidak punya Kubernetes cluster. Awalnya saya memakai kubectl apply --dry-run, tapi ternyata perintah itu mencoba konek ke API server di localhost:8080 dan gagal:
Get "http://localhost:8080/api?timeout=32s": connection refused
Solusinya: validasi schema manifest dengan kubeconform:
kubeconform -strict -ignore-missing-schemas /tmp/dev.yaml
Kubeconform tidak butuh cluster. Ia memeriksa apakah manifest sesuai schema Kubernetes resmi. Jauh lebih cepat dan lebih jujur untuk deployment simulation.
Branch Protection dan Merge Commit
Karena project solo, saya menonaktifkan required PR review. Yang tetap wajib:
- Required status checks:
Build & Test+Security Gate - Force push diblokir
- Branch deletion diblokir
- Conversation resolution wajib
Satu keputusan penting: promotion branch memakai merge commit, bukan squash. Mengapa?
Ketika squash dipakai untuk PR promotion, commit asli diganti satu commit baru. Akibatnya branch develop, staging, dan main terlihat divergen walaupun isinya sama, dan PR berikutnya selalu konflik.
Merge commit menjaga ancestry tetap terbaca:
feature/fix → develop → staging → main
Smoke Test End-to-End
Saya menguji seluruh alur dengan branch feature/test-auto-cd yang hanya mengubah README:
feature/test-auto-cd → develop → staging → main
Hasilnya:
| Tahap | Auto-CD | Hasil |
|---|---|---|
| Merge ke develop | deploy dev | success |
| Merge ke staging | deploy staging | success |
| Merge ke main | deploy prod + verifikasi | success |
Auto-CD benar-benar berjalan tanpa intervensi manual, dan job yang bukan target di-skip dengan benar.
Kesimpulan
Pelajaran hari ini:
- Quality gate harus memeriksa artefak final, bukan hanya source code.
- Approval tidak harus environment gate. Untuk solo project, PR checks + merge commit adalah approval yang cukup.
- Auto-deploy yang aman = CD ter-trigger hanya jika CI sukses, dan target deployment dipilih dari branch pemicu.
- Validasi manifest tidak butuh cluster bila memakai kubeconform.
- Merge commit menjaga ancestry promotion; squash membuat branch terlihat divergen dan memicu konflik.
- Deployment simulation harus jujur — jelaskan bahwa runner cloud tidak mengakses k3d lokal.
File penting ada di repo: chalange-devsecops, terutama .github/workflows/ci.yml, .github/workflows/cd-deploy.yml, securebank-api/k8s/overlays/, dan docs/branching-and-merge-policy.md.
Diskusi & Komentar
Hari 57: Minta AI Merapikan Nada Laporan Audit
Next ArticleHari 59: Panduan Persiapan Ujian CDP DevSecOps
Artikel Terkait
Hari 20: Terraform + Checkov, 15 Celah IaC Ketahuan
Bikin infrastructure as code pakai Terraform, lalu scan dengan Checkov. Hasilnya 15 celah keamanan ketahuan — S3 tanpa enkripsi, security group terbuka ke dunia.
Hari 22: Pipeline IaC, Dua Scanner Barengan Gagal
Bikin workflow GitHub Actions khusus infrastructure security. Checkov dan Trivy IaC scan Terraform barengan. Hasilnya pipeline MERAH — security gate bekerja!
Hari 22 Bonus: Perbaikan Pipeline Gitleaks yang Merah Diam-diam
Pipeline Gitleaks merah sejak Day 14 karena flag --no-gitignore tidak pernah ada. Gitleaks detect scan git history, bukan working directory. Fix: hapus flag.