name: Snapshot Admin Deployment on: push: branches: - main workflow_dispatch: concurrency: group: snapshot-admin-deploy-main cancel-in-progress: true env: DEPLOY_HOST: 178.104.200.7 DEPLOY_USER: kjh2064 TELEGRAM_BOT_TOKEN_DEFAULT: "8734507814:AAFyacLMai8GB4K-hQ_Nd3t3D01A-h1ZdV0" TELEGRAM_CHAT_ID_DEFAULT: "-5460205872" jobs: build-and-deploy: runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: Checkout Code uses: actions/checkout@v3 - name: Setup .NET SDK uses: actions/setup-dotnet@v3 with: dotnet-version: '10.0.x' - name: Publish Blazor Web App run: | echo "[deploy] publishing .NET 10 Blazor app" dotnet publish src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj -c Release -o ./publish - name: Generate Build Info run: | COMMIT_HASH=$(git rev-parse --short HEAD) BUILD_TIME=$(date -d "+9 hours" +'%Y-%m-%d %H:%M:%S KST') mkdir -p ./publish/wwwroot printf '{\n "version": "1.0.%s-%s",\n "built": "%s"\n}\n' "${{ github.run_number }}" "$COMMIT_HASH" "$BUILD_TIME" > ./publish/wwwroot/version.json echo "✓ Generated version info: 1.0.${{ github.run_number }}-$COMMIT_HASH @ $BUILD_TIME" - name: Compress Artifact run: | echo "[deploy] compressing publish output" tar -czf quantengine.tar.gz -C ./publish . - name: Setup SSH run: | mkdir -p ~/.ssh chmod 700 ~/.ssh if echo "${{ secrets.SSH_PRIVATE_KEY }}" | grep -q "BEGIN"; then echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519 else echo "${{ secrets.SSH_PRIVATE_KEY }}" | base64 -d > ~/.ssh/id_ed25519 || echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519 fi chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H ${{ env.DEPLOY_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true - name: Deploy & Verify on Server run: | set -e TIMESTAMP=$(date +%Y%m%d_%H%M%S) COMMIT=$(git rev-parse --short HEAD) DEPLOY_HOST="${{ env.DEPLOY_HOST }}" DEPLOY_USER="${{ env.DEPLOY_USER }}" TELEGRAM_BOT_TOKEN="${{ secrets.TELEGRAM_BOT_TOKEN }}" [ -z "$TELEGRAM_BOT_TOKEN" ] && TELEGRAM_BOT_TOKEN="${{ env.TELEGRAM_BOT_TOKEN_DEFAULT }}" TELEGRAM_CHAT_ID="${{ secrets.TELEGRAM_CHAT_ID }}" [ -z "$TELEGRAM_CHAT_ID" ] && TELEGRAM_CHAT_ID="${{ env.TELEGRAM_CHAT_ID_DEFAULT }}" send_telegram() { local text="$1" curl -fsS -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ -d "chat_id=${TELEGRAM_CHAT_ID}" \ --data-urlencode "text=${text}" \ -d "parse_mode=HTML" >/dev/null || true } notify_failure() { local exit_code=$? send_telegram "❌ Snapshot Admin 배포 실패 커밋: ${COMMIT} 시간: ${TIMESTAMP} 단계: snapshot_admin_deploy (Deploy Execution)" exit "$exit_code" } trap notify_failure ERR echo "=== Deploying Snapshot Admin $COMMIT ($TIMESTAMP) ===" # 1. 원격지 임시 폴더 생성 및 업로드 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p /home/kjh2064/tmp" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 quantengine.tar.gz "$DEPLOY_USER@$DEPLOY_HOST:/home/kjh2064/tmp/quantengine.tar.gz" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 tools/deploy_quantengine.sh "$DEPLOY_USER@$DEPLOY_HOST:/home/kjh2064/tmp/deploy.sh" # 2. 배포 스크립트 실행 ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 "$DEPLOY_USER@$DEPLOY_HOST" "chmod +x /home/kjh2064/tmp/deploy.sh && /home/kjh2064/tmp/deploy.sh" # 3. 배포 성공 검증 echo "=== Verifying Public Routes ===" root_html=$(curl -sf "http://${DEPLOY_HOST}/quant/" 2>/dev/null || echo "") ops_html=$(curl -sf "http://${DEPLOY_HOST}/quant/operations" 2>/dev/null || echo "") root_code=$(printf '%s' "$root_html" | grep -q "Quant Engine" && echo 200 || echo 500) ops_code=$(printf '%s' "$ops_html" | grep -q "Operational Report" && echo 200 || echo 500) echo "/quant/ -> ${root_code}" echo "/quant/operations -> ${ops_code}" if [ "$root_code" != "200" ]; then echo "Deployment content check failed for /quant/" >&2 exit 1 fi if [ "$ops_code" != "200" ]; then echo "Deployment content check failed for /quant/operations" >&2 exit 1 fi echo "✓ 배포 완료: quantengine_${TIMESTAMP} @ $DEPLOY_HOST" send_telegram "✅ Snapshot Admin 배포 완료 커밋: ${COMMIT} 시간: ${TIMESTAMP} 대상: ${DEPLOY_HOST}"