#!/bin/bash # ───────────────────────────────────────────────────────────── # deploy.sh — Skrip deploy produksi (Ubuntu) # Sistem Pemantauan Kemampanan Pusat Data MBIP # # Penggunaan: # ./deploy.sh # deploy / kemas kini (pull, build, up, migrate) # ./deploy.sh --build # paksa bina semula imej Docker # ./deploy.sh --fresh # migrate:fresh --seed (AMARAN: kosongkan data) # ./deploy.sh --logs # ikut log container # ./deploy.sh --down # hentikan container # ───────────────────────────────────────────────────────────── set -euo pipefail cd "$(dirname "$0")" # Guna `docker compose` (v2) atau `docker-compose` (v1) — auto kesan. if docker compose version >/dev/null 2>&1; then DC="docker compose" else DC="docker-compose" fi # Hanya fail produksi (abaikan docker-compose.override.yml untuk dev). COMPOSE_FILES="-f docker-compose.yml" log() { echo -e "\033[0;32m==>\033[0m $*"; } warn() { echo -e "\033[0;33m[!]\033[0m $*"; } die() { echo -e "\033[0;31m[x]\033[0m $*" >&2; exit 1; } # ── Semakan prasyarat ──────────────────────────────────────── command -v docker >/dev/null 2>&1 || die "Docker tidak dipasang." if [ ! -f .env ]; then warn ".env tidak dijumpai — menyalin daripada .env.docker" cp .env.docker .env die "Sila edit .env (APP_KEY, DB_USERNAME, DB_PASSWORD, APP_URL) kemudian jalankan semula ./deploy.sh" fi # ── Kendalikan flag ────────────────────────────────────────── case "${1:-}" in --logs) exec $DC $COMPOSE_FILES logs -f --tail=100 ;; --down) log "Menghentikan container..."; $DC $COMPOSE_FILES down; exit 0 ;; esac FORCE_BUILD=false FRESH=false for arg in "$@"; do case "$arg" in --build) FORCE_BUILD=true ;; --fresh) FRESH=true ;; esac done # ── 1. Tarik kod terkini (jika repo git) ───────────────────── if [ -d .git ]; then log "Menarik kod terkini (git pull)..." git pull --ff-only || warn "git pull gagal / dilangkau." fi # ── 2. Bina aset frontend pada host (Vite) ─────────────────── # Nota: nginx melekap ./public (read-only) terus daripada host, # jadi aset dibina di sini, bukan dalam imej. if command -v npm >/dev/null 2>&1; then log "Membina aset frontend (npm ci && npm run build)..." npm ci --silent || npm install --silent npm run build else warn "npm tidak dijumpai pada host — pastikan public/build sudah dibina." fi # ── 3. Bina / mulakan container ────────────────────────────── if [ "$FORCE_BUILD" = true ]; then log "Membina semula imej Docker..." $DC $COMPOSE_FILES build --pull fi log "Memulakan container..." $DC $COMPOSE_FILES up -d --remove-orphans # ── 4. Tunggu container app sihat ──────────────────────────── log "Menunggu container app sihat..." for i in $(seq 1 30); do if $DC $COMPOSE_FILES exec -T app php-fpm -t >/dev/null 2>&1; then break fi sleep 2 done # ── 5. Migrasi & optimisasi Laravel ────────────────────────── if [ "$FRESH" = true ]; then warn "Menjalankan migrate:fresh --seed (semua data akan dikosongkan)..." $DC $COMPOSE_FILES exec -T --user www-data app php artisan migrate:fresh --seed --force --no-interaction else log "Menjalankan migrasi..." $DC $COMPOSE_FILES exec -T --user www-data app php artisan migrate --force --no-interaction fi log "Memastikan storage symlink..." $DC $COMPOSE_FILES exec -T --user www-data app php artisan storage:link --force || true log "Membina semula cache Laravel..." $DC $COMPOSE_FILES exec -T --user www-data app php artisan optimize:clear $DC $COMPOSE_FILES exec -T --user www-data app php artisan optimize # ── 6. Status ──────────────────────────────────────────────── log "Selesai!" $DC $COMPOSE_FILES ps PORT=$(grep -E '^NGINX_HTTP_PORT=' .env | cut -d= -f2 || echo 8010) log "Aplikasi tersedia pada port ${PORT:-8010} (cth: http://:${PORT:-8010})"