Di dunia pengembangan perangkat lunak yang serba cepat, setiap push kode idealnya langsung diperiksa, dibangun, dan siap rilis—tanpa ritual manual yang memakan waktu. Itulah peran CI/CD (Continuous Integration/Continuous Delivery/Deployment): mengotomatiskan pengujian, build, hingga deployment agar rilis lebih cepat, aman, dan konsisten. GitHub Actions memudahkan semua ini langsung di dalam GitHub: kamu menulis workflow YAML, memilih pemicu (push/PR/jadwal), dan runner GitHub mengeksekusinya untukmu.
Siapa target panduan ini & prasyarat
- Target: developer web/backend/front-end (Node.js/React, Laravel/PHP, Python, Java) yang ingin membuat pipeline CI/CD praktis.
- Prasyarat ringan: punya repo GitHub, bisa commit/push, dan punya skrip build/test dasar pada proyek.
Konsep inti GitHub Actions (singkat & jelas)
- Workflow: file
.yml
di.github/workflows/
berisi alur otomatisasi. - Event/Trigger: pemicu workflow (mis.
push
,pull_request
,workflow_dispatch
,schedule
). - Job: kumpulan langkah (steps) yang berjalan di runner (VM Ubuntu/Windows/macOS).
- Step: perintah shell
run
atau action siap pakai (uses:
). - Runner: mesin eksekusi (mis.
ubuntu-latest
). - Secrets: kredensial aman (token, kunci SSH) di repo Settings → Secrets and variables → Actions.
- Environment: konteks seperti
staging
/production
bisa pakai approval sebelum deploy. - Artifact: file hasil build/test report yang disimpan.
- Cache: mempercepat pipeline (mis. cache dependency).
- Matrix: uji di banyak versi/OS paralel.
- Concurrency: cegah run menumpuk pada branch yang sama.
Gambaran besar alur CI/CD
1.CI saat push/PR: checkout → install dependensi → lint → test → build → upload artifact.
2.CD setelah CI lulus:
- Frontend → GitHub Pages/VPS.
- Backend → bangun image Docker, push ke registry (GHCR/Docker Hub), lalu deploy (VPS/Kubernetes/Cloud).
3.Environment & Approval: staging otomatis, production butuh persetujuan.
4.Release/Tag (opsional): tandai versi untuk audit/rollback.
Persiapan repo (5 menit)
1.Buat folder .github/workflows/
.
2.Pastikan ada skrip di proyek (contoh Node.js di package.json
):
{
"scripts": {
"lint": "eslint .",
"test": "vitest run --coverage",
"build": "vite build" } }
(Ganti sesuai stack: php artisan test
, pytest
, mvn test
, dll.)
3.Tambahkan secrets yang diperlukan (contoh):
- Deploy SSH:
SSH_HOST
,SSH_USER
,SSH_KEY
(private key). - Docker Hub:
DOCKERHUB_USERNAME
,DOCKERHUB_TOKEN
. - Cloud/OIDC: kredensial/role yang diperlukan.
Bagian A — CI dasar (lint, test, build + artifact)
File: .github/workflows/ci.yml
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
permissions:
contents: read # prinsip least privilege
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true # batalkan run lama jika ada yang baru
jobs:
build-test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install deps
run: npm ci
- name: Lint
run: npm run lint --if-present
- name: Test
run: npm test --if-present
- name: Build
run: npm run build --if-present
- name: Upload artifact (build output)
if: success()
uses: actions/upload-artifact@v4
with:
name: app-dist
path: |
dist
build
Kenapa ini penting: memastikan setiap perubahan selalu teruji & bisa dibangun di lingkungan bersih (runner), bukan hanya di laptopmu.
Alternatif setup bahasa lain (di step “Setup …”):
- Python:
actions/setup-python@v5
+pip install -r requirements.txt
+pytest
- PHP/Laravel:
shivammathur/setup-php@v2
+composer install
+php artisan test
- Java/Maven:
actions/setup-java@v4
+mvn -B verify
Bagian B — Continuous Delivery: build & push Docker image
Bangun image & push ke GitHub Container Registry (GHCR) setiap push ke main
.
File: .github/workflows/docker.yml
name: Docker CI/CD
on:
push:
branches: [ main ]
paths:
- 'Dockerfile'
- '**/*.ts'
- '**/*.js'
- 'package.json'
- 'pnpm-lock.yaml'
- 'package-lock.json'
permissions:
contents: read
packages: write
id-token: write # disarankan untuk OIDC ke cloud (opsional)
env:
IMAGE_NAME: ghcr.io/${{ github.repository }}
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up QEMU (multi-arch)
uses: docker/setup-qemu-action@v3
- name: Set up Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_NAME }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
Pakai Docker Hub? Ubah login:
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
env:
IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/nama-image
Bagian C — Continuous Deployment (opsi yang paling umum)
Opsi 1: Deploy frontend ke GitHub Pages (SPA/React/Vite)
Sekali di UI: Settings → Pages → Source: GitHub Actions.
File: .github/workflows/pages.yml
name: Deploy to GitHub Pages
on:
push:
branches: [ main ]
workflow_dispatch: {}
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: production
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Tips SPA: atur base
di vite.config
(jika repo bukan root) dan SPA fallback bila perlu.
Opsi 2: Deploy ke VPS via SSH (statik/backend Node)
Prasyarat server: user non-root, public key ada di ~/.ssh/authorized_keys
, web root jelas.
Secrets: SSH_HOST
, SSH_USER
, SSH_KEY
.
File: .github/workflows/deploy-ssh.yml
name: Deploy to VPS via SSH
on:
push:
branches: [ main ]
workflow_dispatch: {}
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
url: https://your-domain.com
steps:
- uses: actions/checkout@v4
- name: Build app (contoh front-end)
run: |
npm ci
npm run build
- name: Upload build to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
source: "dist/*"
target: "/var/www/myapp"
- name: Restart service (contoh backend Node)
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/myapp
pm2 reload myapp || pm2 start server.js --name myapp
Opsi 3: Deploy ke Cloud via OIDC (contoh AWS S3 static hosting)
Ide: tanpa static keys; runner menukar ID Token ke kredensial sementara.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployer
aws-region: ap-southeast-1
- name: Sync to S3
run: aws s3 sync dist s3://nama-bucket --delete
Opsi 4: Kubernetes (ringkas)
Asumsikan kubeconfig disimpan di secret KUBE_CONFIG
.
- name: Set kubeconfig
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" > $HOME/.kube/config
- name: Rollout new image
run: |
kubectl set image deployment/myapp myapp=${{ env.IMAGE_NAME }}:latest
kubectl rollout status deployment/myapp
Bagian D — Monorepo & workflow pintar
Jalankan hanya saat folder tertentu berubah:
on:
push:
branches: [ main ]
paths:
- 'apps/web/**'
- '!**.md'
Gunakan filter canggih (dorny/paths-filter) + fan-out jobs:
jobs:
changes:
runs-on: ubuntu-latest
outputs:
web: ${{ steps.filter.outputs.web }}
api: ${{ steps.filter.outputs.api }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
web:
- 'apps/web/**'
api:
- 'apps/api/**'
web-ci:
needs: changes
if: needs.changes.outputs.web == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ... langkah CI untuk web
api-ci:
needs: changes
if: needs.changes.outputs.api == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ... langkah CI untuk api
Reusable workflow (antar-repo/proyek):
# .github/workflows/reuse-ci.yml
name: Reusable CI
on:
workflow_call:
inputs:
node:
required: true
type: string
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node }}
- run: npm ci && npm test && npm run build
Pemanggil:
jobs:
use-shared-ci:
uses: owner/repo/.github/workflows/reuse-ci.yml@main
with:
node: '20'
Bagian E — Keamanan & izin (harus dibaca!)
- Least privilege: set
permissions
minimal; buka hanya yang perlu (mis.packages: write
saat push image). - Jangan pernah mencetak secrets ke log.
- Pisahkan secrets per-environment (staging vs production).
- Pin actions minimal ke major (lebih ketat: ke commit SHA) untuk mengurangi risiko supply chain.
- Branch protection: wajibkan PR review + status checks (CI) lulus sebelum merge.
- Dependabot: otomatisasi update dependency & actions.
Bagian F — Observability & troubleshooting
- Logs: buka run → klik job → step → lihat log (error jelas di sini).
- Rerun: jalankan ulang job/step yang gagal.
- Debug verbose: aktifkan
ACTIONS_STEP_DEBUG=true
di repo (Settings → Actions → enable debug). - Masalah umum & solusinya:
Gejala | Penyebab Umum | Solusi Cepat |
---|---|---|
Cache tidak pernah hit | key tidak stabil/path salah | Pakai hashFiles pada lockfile, cek path |
Gagal push ke GHCR/Docker | permissions kurang | Tambah packages: write (GHCR) / login action Docker |
SSH gagal | Format key/izin server | Pastikan OpenSSH key, izin file benar, IP runner diizinkan |
SPA di Pages 404 | Tidak ada fallback/base | Atur base & fallback SPA (config bundler/redirects) |
Build berbeda dgn lokal | Versi Node/OS beda | Tetapkan versi (matrix), pakai npm ci , bersihkan cache |
Checklist implementasi cepat
- CI lint + test + build + upload artifact
- CD: build & push Docker (opsional)
- CD: deploy (GitHub Pages / VPS / Cloud / K8s)
- Environment
staging
&production
+ approval - Secrets aman &
permissions
minimal - Concurrency untuk cegah job menumpuk
- Filter paths / reusable workflows (untuk monorepo)
- Dependabot & pin actions
Kesimpulan (versi inspiratif & profesional)
GitHub Actions mengubah setiap push menjadi proses rilis yang teruji, bisa direproduksi, dan siap produksi—tanpa kerja manual berulang. Dengan pipeline CI/CD yang rapi, kamu bukan hanya mempercepat rilis fitur; kamu juga meningkatkan kualitas, mengurangi risiko, dan memberi tim ruang untuk fokus pada hal yang benar-benar penting: membangun produk yang hebat. Mulailah dari CI dasar, tambahkan CD yang sesuai target deploy-mu, lalu tingkatkan keamanan dan kecepatan seiring kebutuhan—pipeline-mu akan tumbuh bersama produkmu.