34. CI/CD Pipeline & Local Validation
Proses pengembangan software sekarang dituntut serba cepat, tapi kodenya harus tetap stabil dan berkualitas. Makanya, kita menerapkan prinsip Shift-Left Validation. Konsepnya sederhana: kita memindahkan proses testing dan validasi sedini mungkin ke lingkungan lokal (komputer developer) sebelum kodenya masuk ke repositori utama.
Dengan melakukan validasi secara lokal, feedback loop jadi lebih cepat, kita bisa menghemat waktu build di server CI/CD, menghemat resource runner, dan memastikan branch utama (main/master) selalu aman dan siap deploy kapan saja (always deployable).
A. Alur Validasi Kode (Validation Workflow)
Berikut adalah diagram alur verifikasi kode dari komputer lokal sampai dideploy lewat server CI/CD:
graph TD
A[Developer Menulis Kode] --> B[Simpan File / Git Commit]
B --> C{Git Hook: Husky & lint-staged}
C -- Ada Error Lint/Type/Test --> D[Commit Ditolak & Perbaiki di Lokal]
C -- Sukses --> E[Push ke Repositori Remote]
E --> F[Picu Pipeline CI/CD di Server]
F --> G{Pemeriksaan CI/CD Pipeline}
G -- Gagal --> H[Kirim Notifikasi Gagal & Blok Merge]
H --> A
G -- Sukses --> I[Merge ke Branch Utama & Deploy]
B. Validasi Lokal (Local Validation Checklist)
Sebelum melakukan push atau membuat commit, developer sebaiknya menjalankan checklist validasi berikut secara mandiri di komputer masing-masing:
1. Code Formatting (Prettier)
Memastikan semua file rapi sesuai standar penulisan kode. Langkah ini membantu menghindari perdebatan seputar format kode (seperti koma, spasi, dll.) saat code review.
# Memeriksa apakah ada file yang melanggar format
npm run format:check
# Memperbaiki format kode secara otomatis di semua file
npm run format:write
2. Static Analysis & Linting (ESLint)
Mendeteksi pola kode yang kurang baik (anti-patterns), variabel yang tidak terpakai, dan potensi bug sebelum kode dijalankan.
# Menjalankan linter untuk mencari masalah kode
npm run lint
# Memperbaiki masalah linting ringan secara otomatis
npm run lint -- --fix
3. Type Checking (TypeScript Compiler)
Memastikan keamanan tipe data (type safety) di seluruh project. Proses build biasa kadang mengabaikan error tipe data jika tidak dikonfigurasi dengan ketat.
# Menjalankan type-check tanpa menghasilkan file build
npm run type-check
# atau secara langsung:
npx tsc --noEmit
4. Automated Testing (Unit & Integration)
Memastikan perubahan kode baru tidak merusak fitur lama yang sudah berjalan (regression testing).
# Menjalankan semua test
npm run test
# Menjalankan test untuk file yang berubah saja (Watch Mode)
npm run test:watch
5. Local Production Build Simulation
Kadang kode berjalan lancar di mode development (npm run dev), tapi gagal saat di-build untuk production karena masalah optimasi compiler, circular dependencies, atau file yang hilang. Selalu jalankan build lokal sebelum membuat Pull Request (PR).
# Simulasi membuat production build secara lokal
npm run build
C. Otomatisasi Validasi Lokal Menggunakan Git Hooks
Menjalankan lima langkah di atas secara manual setiap kali akan commit tentu kurang efisien dan rentan terlewat. Untuk memudahkan, kita bisa mengotomatisasikannya menggunakan Husky dan lint-staged.
[!IMPORTANT] lint-staged sangat membantu memastikan pemeriksaan hanya berjalan pada file yang sedang diubah (staged files), bukan seluruh project. Hal ini menjaga proses
git committetap berjalan cepat (di bawah 10 detik).
1. Instalasi Dependensi
npm install -D husky lint-staged
2. Inisialisasi Husky
npx husky-init
npm install
Perintah ini akan membuat folder .husky/ di direktori utama dan menambahkan script prepare di package.json.
3. Konfigurasi lint-staged di package.json
Tambahkan konfigurasi berikut di package.json untuk menentukan file mana saja yang perlu diperiksa:
{
"scripts": {
"prepare": "husky install"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{json,md,css,scss}": [
"prettier --write"
]
}
}
4. Konfigurasi Git Pre-commit Hook (.husky/pre-commit)
Ubah isi file .husky/pre-commit menjadi seperti di bawah ini. File ini akan berjalan otomatis setiap kali melakukan git commit.
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo "=== Memulai Validasi Pre-Commit ==="
# 1. Jalankan Type-Check pada file TypeScript (memerlukan konteks seluruh proyek)
echo "🔍 Menjalankan TypeScript Type-Check..."
npx tsc --noEmit || {
echo "❌ TypeScript Type-Check gagal! Silakan perbaiki error tipe data sebelum commit."
exit 1
}
# 2. Jalankan lint-staged untuk memformat dan memeriksa file yang diubah
echo "🧹 Menjalankan ESLint & Prettier pada staged files..."
npx lint-staged || {
echo "❌ Linting atau formatting gagal!"
exit 1
}
# 3. Jalankan unit test untuk file yang berubah (sangat direkomendasikan)
echo "🧪 Menjalankan Unit Test..."
npm run test:related || npm run test -- --watchAll=false --findRelatedTests $(git diff --staged --name-only) || {
echo "❌ Unit test gagal!"
exit 1
}
echo "✅ Validasi berhasil! Melanjutkan commit."
D. Standardisasi CI/CD Pipeline Server
Meskipun validasi lokal sudah berjalan, server CI/CD tetap bertindak sebagai Gatekeeper Utama. Server CI/CD menjamin pengujian berjalan di lingkungan yang bersih (clean slate) dan terisolasi dari cache komputer developer.
1. Aturan Penggunaan npm ci vs npm install
Di server CI/CD, sebaiknya gunakan npm ci (Clean Install) alih-alih npm install. Keuntungannya:
- Menghapus folder
node_modulesyang ada untuk memastikan dependensi bersih. - Mengunduh dependensi sesuai dengan
package-lock.jsonuntuk menjamin versi yang sama dengan komputer lokal. - Tidak memperbarui
package-lock.jsonsecara otomatis, menghindari efek samping perubahan versi. - Proses instalasi lebih cepat dibanding
npm installbiasa.
2. Contoh Konfigurasi GitLab CI/CD (.gitlab-ci.yml)
Berikut contoh konfigurasi multi-stage untuk GitLab CI/CD (.gitlab-ci.yml):
# Menggunakan image node versi LTS
image: node:20-alpine
# Aktifkan cache node_modules untuk mempercepat build berikutnya
cache:
key:
files:
- package-lock.json
paths:
- .npm/
- node_modules/
stages:
- install
- test
- build
- deploy
# Stage 1: Instalasi dependensi
install_dependencies:
stage: install
script:
- npm ci --cache .npm --prefer-offline
artifacts:
paths:
- node_modules/
expire_in: 1 hour
# Stage 2: Pemeriksaan kualitas kode & test
code_quality_and_test:
stage: test
dependencies:
- install_dependencies
script:
- npm run lint
- npx tsc --noEmit
- npm run test -- --coverage --watchAll=false
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
artifacts:
reports:
junit: junit.xml
# Stage 3: Proses build
build_project:
stage: build
dependencies:
- install_dependencies
script:
- npm run build
artifacts:
paths:
- dist/
- .next/
expire_in: 1 week
only:
- main
- merge_requests
# Stage 4: Deployment (Contoh ke Staging/Production)
deploy_to_staging:
stage: deploy
dependencies:
- build_project
script:
- echo "Deploying to Staging Server..."
- # Jalankan script deployment di sini (AWS S3, Vercel CLI, Docker, dll)
environment:
name: staging
url: https://staging.company.com
only:
- main
3. Contoh Konfigurasi GitHub Actions (.github/workflows/ci.yml)
Berikut contoh konfigurasi untuk GitHub Actions (.github/workflows/ci.yml):
name: Frontend CI/CD Pipeline
on:
push:
branches: [ main, staging ]
pull_request:
branches: [ main, staging ]
jobs:
validate-and-build:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # Caching otomatis untuk dependensi npm
- name: Install Dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
- name: Run TypeScript Type-Check
run: npx tsc --noEmit
- name: Run Unit Tests
run: npm run test -- --watchAll=false
- name: Build Application
run: npm run build
- name: Upload Build Artifacts
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
uses: actions/upload-artifact@v4
with:
name: production-build
path: |
.next/
dist/
public/
package.json
retention-days: 7
E. Best Practices dalam CI/CD
Untuk menjaga pipeline berjalan efisien dan aman, ikuti prinsip-prinsip berikut:
- Dependency Caching: Selalu konfigurasikan caching untuk folder
node_modulesatau cache NPM (.npm). Ini dapat mempersingkat waktu build hingga 50% - 70%. - Secrets & Environment Variables:
-
[!WARNING] Jangan menyimpan file
.envatau secret keys di dalam repositori Git. - Simpan kredensial sensitif di menu Variables (GitLab CI/CD) atau Secrets (GitHub Settings).
- Panggil nilai tersebut di dalam pipeline menggunakan environment variable (contoh:
process.env.API_KEY).
-
- Pipeline Fail-Fast: Tempatkan pengujian yang paling cepat (seperti linting) di tahap awal. Jika tahap awal ini gagal, hentikan pipeline segera untuk menghemat waktu dan resource komputasi.
F. Panduan Pemecahan Masalah (Troubleshooting)
Kasus 1: "Lokal sukses berjalan, tetapi CI/CD gagal build"
- Kemungkinan Penyebab A: Perbedaan sensitivitas huruf besar/kecil (case-sensitivity) pada nama file. Komputer macOS/Windows secara default bersifat case-insensitive, sedangkan server Linux CI/CD bersifat case-sensitive.
- Solusi: Pastikan impor file sesuai persis dengan nama file fisik (misal:
import Card from './Card'bukanimport Card from './card').
- Solusi: Pastikan impor file sesuai persis dengan nama file fisik (misal:
- Kemungkinan Penyebab B: Dependensi yang terpasang di lokal tidak tercatat di
package.jsonatau terpasang sebagai package global.- Solusi: Jalankan
npm cidi folder baru secara lokal untuk mensimulasikan lingkungan server.
- Solusi: Jalankan
Kasus 2: "Proses Type-Checking lambat di CI/CD"
- Solusi: Pastikan Anda menyertakan opsi
skipLibCheck: truedi dalam berkastsconfig.jsonproyek untuk menghindari pemeriksaan tipe data pada berkas pihak ketiga dinode_modules.
G. Matriks Perbandingan Validasi
| Dimensi Validasi | Lingkungan Lokal (Local) | Lingkungan CI/CD (Server) | Frekuensi Eksekusi |
|---|---|---|---|
| Formatting | Menggunakan Prettier otomatis saat menyimpan berkas atau git commit. | prettier --check memastikan tidak ada bypass kode yang tidak rapi. | Setiap commit & PR check. |
| Linting | Integrasi IDE memberikan info error langsung saat mengetik. | ESLint memeriksa secara mutlak sebelum penggabungan kode (merge). | Instan di IDE & saat PR check. |
| Type Checking | Evaluasi incremental di latar belakang oleh IDE atau tsc --noEmit manual. | Pemeriksaan penuh dari awal untuk menghindari kesalahan tipe data. | Setiap commit & PR check. |
| Testing | Menjalankan test-suite spesifik yang terkait dengan file yang diubah. | Menjalankan seluruh pengujian dari awal beserta perhitungan coverage. | Setiap commit & PR check. |
| Building | Opsional dijalankan mandiri sebelum membuat Pull Request. | Wajib dijalankan untuk memvalidasi output bundler sebelum proses deploy. | Setiap PR & deploy branch. |
© 2026. Technical Excellence Standard.