77 - " backend/**"
88 - " .github/workflows/deploy-backend.yml"
99 - ' !**/**/*.md'
10+ workflow_dispatch :
1011
11- workflow_dispatch : # Memungkinkan trigger deployment secara manual dari GitHub Actions UI
12+ # ✅ 1. WAJIB DEFINISIKAN ENV DI ROOT AGAR TIDAK NYASAR KE DOCKER HUB!
13+ env :
14+ REGISTRY : ghcr.io
15+ # Menggunakan lowercase otomatis untuk menghindari error GHCR uppercase
16+ IMAGE_NAME : ${{ github.repository }}-backend
1217
1318jobs :
19+ # ==========================================================
20+ # JOB 1: CONTINUOUS INTEGRATION (TYPECHECK & TEST)
21+ # ==========================================================
1422 build-and-test :
15- name : Build & Test (Bun)
23+ name : 1. Build & Test (Bun)
1624 runs-on : ubuntu-latest
1725 defaults :
1826 run :
@@ -36,12 +44,16 @@ jobs:
3644 - name : Run Unit Tests
3745 run : bun test
3846
47+ # ==========================================================
48+ # JOB 2: BUILD & PUSH IMAGE KE GHCR
49+ # ==========================================================
3950 build-and-push-ghcr :
40- name : Build & Push Backend Docker Image to GHCR
51+ name : 2. Build & Push Docker Image to GHCR
52+ needs : build-and-test # ✅ KUNCI: Harus nunggu Job 1 sukses!
4153 runs-on : ubuntu-latest
4254 permissions :
4355 contents : read
44- packages : write
56+ packages : write # ✅ KUNCI: Izin push ke GHCR
4557
4658 steps :
4759 - name : Checkout repository
7991 cache-from : type=gha
8092 cache-to : type=gha,mode=max
8193
94+ # ==========================================================
95+ # JOB 3: DEPLOY KE SERVER PRODUCTION VPS VIA SSH
96+ # ==========================================================
8297 deploy-to-production :
83- name : Deploy to Server & Run Migrations
98+ name : 3. Deploy to Server & Run Migrations
99+ needs : build-and-push-ghcr # ✅ KUNCI: Harus nunggu Job 2 sukses!
84100 runs-on : ubuntu-latest
85101 environment : staging
86102
97113 key : ${{ secrets.SSH_PRIVATE_KEY }}
98114 source : " backend/docker-compose.yml"
99115 target : " ${{ secrets.DEPLOY_PATH_BACKEND }}"
116+ strip_components : 1 # ✅ KUNCI: Letakkan langsung docker-compose.yml di target!
100117
101118 - name : Deploy & Execute DB Migrations via SSH
102119 uses : appleboy/ssh-action@v1.0.3
@@ -106,50 +123,47 @@ jobs:
106123 port : ${{ secrets.SERVER_PORT || '22' }}
107124 key : ${{ secrets.SSH_PRIVATE_KEY }}
108125 command_timeout : 30m
109- script_stop : true
126+ script_stop : true # ✅ KUNCI: Hentikan langsung jika ada error 1 pun!
110127 script : |
111128 echo "=========================================================="
112- echo " [1/5] Masuk ke direktori aplikasi & Git Pull "
129+ echo " [1/5] Masuk ke direktori aplikasi"
113130 echo "=========================================================="
114131 DEPLOY_DIR="${{ secrets.DEPLOY_PATH_BACKEND }}"
115132 echo "Directori target deployment: $DEPLOY_DIR"
133+ mkdir -p "$DEPLOY_DIR"
116134 cd "$DEPLOY_DIR" || exit 1
117135
118- # Jika folder server menggunakan git repo, jalankan pull; jika tidak (hanya hasil SCP), abaikan:
119- if [ -d ".git" ]; then
120- git fetch --all
121- git reset --hard origin/main
122- fi
123-
124136 echo "=========================================================="
125- echo " [2/5] Menulis file .env di dalam folder backend/ "
137+ echo " [2/5] Menulis file .env production "
126138 echo "=========================================================="
139+ # Menulis file .env di level direktori yang sama dengan docker-compose.yml
127140 cat <<'EOF_ENV' > .env
128141 ${{ secrets.ENV_PROD_BACKEND }}
129142 EOF_ENV
130- mkdir -p backend
131- cp .env backend/.env
132- chmod 600 .env backend/.env
143+ chmod 600 .env
133144
134145 echo "=========================================================="
135146 echo " [3/5] Mengunduh Docker Image terbaru dari GHCR"
136147 echo "=========================================================="
137- # Login ke GHCR dan pull image (agar server tidak membebani CPU/RAM untuk build)
138- echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin || true
139- docker pull ghcr.io/${{ github.repository }}-backend:latest
148+ # Ubah nama repositori ke lowercase via bash syntax (GHCR menolak uppercase)
149+ REPO_LOWER=$(echo "${{ github.repository }}-backend" | tr '[:upper:]' '[:lower:]')
150+ IMAGE_TARGET="ghcr.io/${REPO_LOWER}:latest"
151+
152+ echo "Pulling image: $IMAGE_TARGET"
153+ docker pull "$IMAGE_TARGET"
140154
141155 echo "=========================================================="
142156 echo " [4/5] Menjalankan Database Migrations via Drizzle ORM"
143157 echo "=========================================================="
144- # Memastikan proxy_network dan minigrafana-net tersedia di server
145158 docker network inspect proxy_network >/dev/null 2>&1 || docker network create proxy_network
146159 docker network inspect minigrafana-net >/dev/null 2>&1 || docker network create minigrafana-net
147160
148161 # Menjalankan migrasi Drizzle secara terisolasi ke database production
149- docker run --rm --network minigrafana-net --env-file backend/ .env ghcr.io/${{ github.repository }}-backend:latest bun run db:migrate:prod
162+ docker run --rm --network minigrafana-net --env-file .env "$IMAGE_TARGET" bun run db:migrate:prod
150163
151164 echo "=========================================================="
152165 echo " [5/5] Merestart Container Aplikasi Backend"
153166 echo "=========================================================="
154- cd backend && docker compose up -d --force-recreate
155- echo "✅ Deployment dan Migrasi Database selesai!"
167+ docker compose up -d --force-recreate --remove-orphans
168+ docker image prune -f
169+ echo "✅ Deployment dan Migrasi Database selesai!"
0 commit comments