From 42fc2d9136f105da571d6ec8c544f8090e56b717 Mon Sep 17 00:00:00 2001 From: PhuocNTB Date: Wed, 1 Jul 2026 07:39:55 +0700 Subject: [PATCH] add config cicd --- .gitea/workflows/deploy.yml | 64 +++++++++++++++++++ management/src/api.ts | 17 ++++- .../src/components/ProctorStreamPanels.tsx | 4 +- management/src/hooks/useStaffChatSocket.ts | 5 +- 4 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 .gitea/workflows/deploy.yml diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..af761d4 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,64 @@ +name: Deploy on Master Change +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened] + branches: + - master + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout code (with full history + correct branch) + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Lấy toàn bộ history + ref: master # Đảm bảo checkout đúng branch master + + - name: Deploy to server + env: + SSH_IP: ${{ secrets.SSH_IP }} + SSH_PORT: ${{ secrets.SSH_PORT }} + SSH_USER: ${{ secrets.SSH_USER }} + SSH_PASS: ${{ secrets.SSH_PASSWORD }} + run: | + # Cài sshpass + sudo apt-get update -y + sudo apt-get install -y sshpass + + echo "Đang deploy lên server..." + + sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no -p "$SSH_PORT" "$SSH_USER@$SSH_IP" << 'EOF' + set -e + + cd /var/www/simple_care + + echo "Force update code từ remote (hỗ trợ cả force push)" + git fetch --all + git reset --hard origin/master + git clean -fd + + # Load NVM for node/npm + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + + echo "Build management frontend..." + cd management + npm install + VITE_API_BASE=https://sv.rikkeiraia.org/api npm run build + cd .. + + echo "Build server backend..." + cd server + go build -o serverlinux main.go + + echo "Khởi động lại PM2..." + pm2 delete raia_v3_server || pm2 delete serverlinux || true + pm2 start ./serverlinux --name raia_v3_server + pm2 save # lưu lại trạng thái pm2 + + echo "Deploy thành công!" + EOF \ No newline at end of file diff --git a/management/src/api.ts b/management/src/api.ts index 1b16e32..8bc4197 100644 --- a/management/src/api.ts +++ b/management/src/api.ts @@ -1,4 +1,19 @@ -const API_BASE = 'http://127.0.0.1:8080/api'; +export const API_BASE = import.meta.env.VITE_API_BASE || 'http://127.0.0.1:8080/api'; + +export function getWsUrl(path: string): string { + try { + if (API_BASE.startsWith('http://') || API_BASE.startsWith('https://')) { + const url = new URL(API_BASE); + const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'; + return `${protocol}//${url.host}${path}`; + } + } catch (e) { + // ignore + } + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + return `${protocol}//${window.location.host}${path}`; +} + function getToken(): string | null { return localStorage.getItem('sc_staff_token'); diff --git a/management/src/components/ProctorStreamPanels.tsx b/management/src/components/ProctorStreamPanels.tsx index f11f1ec..571be2b 100644 --- a/management/src/components/ProctorStreamPanels.tsx +++ b/management/src/components/ProctorStreamPanels.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useState, useRef, useCallback } from 'react'; +import { getWsUrl } from '../api'; interface ProctorStreamPanelsProps { studentId: number; @@ -30,8 +31,7 @@ export const ProctorStreamPanels: React.FC = ({ const webcamZoom = ZOOM_STEPS[webcamZoomIdx]; useEffect(() => { - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; - const wsUrl = `${protocol}//${window.location.hostname}:8080/ws?role=teacher`; + const wsUrl = getWsUrl('/ws?role=teacher'); intentionalClose.current = false; hasOpened.current = false; diff --git a/management/src/hooks/useStaffChatSocket.ts b/management/src/hooks/useStaffChatSocket.ts index 53d2470..2571a07 100644 --- a/management/src/hooks/useStaffChatSocket.ts +++ b/management/src/hooks/useStaffChatSocket.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect, useRef } from 'react'; -import { type ChatMessage } from '../api'; +import { type ChatMessage, getWsUrl } from '../api'; import { useAuth } from '../auth/AuthContext'; import { playChatSound } from '../utils/notifySound'; @@ -28,8 +28,7 @@ export function StaffChatSocket() { useEffect(() => { if (!token || !staff?.id) return; - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; - const wsUrl = `${protocol}//${window.location.hostname}:8080/ws?role=teacher&staffId=${staff.id}`; + const wsUrl = getWsUrl(`/ws?role=teacher&staffId=${staff.id}`); let ws: WebSocket | null = null; let retryTimer: ReturnType | null = null; let closed = false;