fix(ci): use git-pull pattern like ZeaVis-Edu, all images from GHCR

- Replace build: blocks with image: from ghcr.io
- Simplify deploy: git clone/pull on VPS, then docker compose pull/up
- Remove SCP step entirely — nginx.conf baked into proxy image
- Rename containers to imphenbot-* to match existing VPS setup
- Fix backend port to 3000 for production

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-02 09:41:38 +07:00
co-authored by Claude Opus 4.8
parent 8c4b32f5e1
commit 73efc716a5
2 changed files with 31 additions and 51 deletions
+15 -21
View File
@@ -19,6 +19,7 @@ jobs:
build-and-push: build-and-push:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false
matrix: matrix:
service: [frontend, backend, discord-gateway, proxy] service: [frontend, backend, discord-gateway, proxy]
steps: steps:
@@ -55,20 +56,8 @@ jobs:
deploy: deploy:
needs: build-and-push needs: build-and-push
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
steps: steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: SCP deploy files to VPS
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USERNAME }}
key: ${{ secrets.VPS_SSH_KEY }}
source: "infra/docker/*"
target: "/tmp/bete-deploy"
strip_components: 2
- name: Deploy to VPS - name: Deploy to VPS
uses: appleboy/ssh-action@v1.2.5 uses: appleboy/ssh-action@v1.2.5
env: env:
@@ -84,20 +73,25 @@ jobs:
set -eu set -eu
APP_DIR=/opt/imphenbot APP_DIR=/opt/imphenbot
mkdir -p "$APP_DIR" "$APP_DIR/nginx" REPO_URL=https://github.com/MythEclipse/bete.git
if [ ! -d "$APP_DIR/.git" ]; then
mkdir -p "$APP_DIR"
git clone "$REPO_URL" "$APP_DIR"
fi
cd "$APP_DIR" cd "$APP_DIR"
git fetch origin master
git checkout master
git reset --hard origin/master
printf '%s\n' "$ENV_FILE" > .env printf '%s\n' "$ENV_FILE" > .env
# Copy deploy files from SCP staging dir
cp /tmp/bete-deploy/docker-compose.yml "$APP_DIR/docker-compose.yml"
cp /tmp/bete-deploy/nginx.conf "$APP_DIR/nginx/nginx.conf"
mkdir -p recordings mkdir -p recordings
echo "$GHCR_TOKEN" | docker login ghcr.io -u "$GHCR_USERNAME" --password-stdin echo "$GHCR_TOKEN" | docker login ghcr.io -u "$GHCR_USERNAME" --password-stdin
docker compose pull docker compose -f infra/docker/docker-compose.yml pull
docker compose down --remove-orphans || true docker compose -f infra/docker/docker-compose.yml down --remove-orphans || true
docker compose up -d --remove-orphans docker compose -f infra/docker/docker-compose.yml up -d --remove-orphans
docker image prune -f docker image prune -f
+16 -30
View File
@@ -3,17 +3,15 @@ version: '3.8'
services: services:
# Nginx Reverse Proxy — handles /api and /ws routing behind Traefik # Nginx Reverse Proxy — handles /api and /ws routing behind Traefik
proxy: proxy:
build: image: ghcr.io/${OWNER:-mytheclipse}/bete-proxy:latest
context: . container_name: imphenbot-proxy
dockerfile: Dockerfile.nginx
container_name: bete-proxy
restart: unless-stopped restart: unless-stopped
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.http.routers.bete.rule=Host(`imphnen.asepharyana.my.id`)" - "traefik.http.routers.imphenbot.rule=Host(`imphnen.asepharyana.my.id`)"
- "traefik.http.routers.bete.entrypoints=websecure" - "traefik.http.routers.imphenbot.entrypoints=websecure"
- "traefik.http.routers.bete.tls=true" - "traefik.http.routers.imphenbot.tls=true"
- "traefik.http.services.bete.loadbalancer.server.port=80" - "traefik.http.services.imphenbot.loadbalancer.server.port=80"
depends_on: depends_on:
- backend - backend
- frontend - frontend
@@ -22,17 +20,14 @@ services:
# Backend Service (REST API + WebSocket) # Backend Service (REST API + WebSocket)
backend: backend:
build: image: ghcr.io/${OWNER:-mytheclipse}/bete-backend:latest
context: .. container_name: imphenbot-backend
dockerfile: infra/docker/Dockerfile.backend
container_name: bete-backend
restart: unless-stopped restart: unless-stopped
env_file: env_file:
- ../../.env - .env
environment: environment:
NODE_ENV: production NODE_ENV: production
WEBSERVER_PORT: 3001 WEBSERVER_PORT: 3000
# No Traefik labels — nginx handles routing
depends_on: depends_on:
- discord-gateway - discord-gateway
networks: networks:
@@ -40,32 +35,23 @@ services:
# Discord Gateway Service (Event capture and processing — no HTTP) # Discord Gateway Service (Event capture and processing — no HTTP)
discord-gateway: discord-gateway:
build: image: ghcr.io/${OWNER:-mytheclipse}/bete-discord-gateway:latest
context: .. container_name: imphenbot-discord-gateway
dockerfile: infra/docker/Dockerfile.discord-gateway
container_name: bete-discord-gateway
restart: unless-stopped restart: unless-stopped
env_file: env_file:
- ../../.env - .env
environment: environment:
NODE_ENV: production NODE_ENV: production
volumes: volumes:
- ../recordings:/app/recordings - ./recordings:/app/recordings
networks: networks:
- app-shared-net - app-shared-net
# Frontend Service (React Dashboard) # Frontend Service (React Dashboard)
frontend: frontend:
build: image: ghcr.io/${OWNER:-mytheclipse}/bete-frontend:latest
context: .. container_name: imphenbot-frontend
dockerfile: infra/docker/Dockerfile.frontend
container_name: bete-frontend
restart: unless-stopped restart: unless-stopped
environment:
# Point to the same domain — nginx routes /api and /ws to backend
VITE_BE_API_URL: https://imphnen.asepharyana.my.id
VITE_BE_WS_URL: wss://imphnen.asepharyana.my.id
# No Traefik labels — nginx handles routing
networks: networks:
- app-shared-net - app-shared-net