Skip to content

chore: cập nhật cấu trúc mã và cải tiến xử lý webhook GHN #404

chore: cập nhật cấu trúc mã và cải tiến xử lý webhook GHN

chore: cập nhật cấu trúc mã và cải tiến xử lý webhook GHN #404

Workflow file for this run

name: CI/CD Pipeline Optimized
on:
push:
branches: [main, master]
workflow_dispatch:
inputs:
manual_rollback:
description: 'Commit SHA hoặc tag để rollback'
required: false
permissions:
contents: write
jobs:
deploy:
name: Deploy to Production
runs-on: ubuntu-latest
if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && !github.event.inputs.manual_rollback) }}
steps:
- name: Record Job Start Time
id: start_time
run: echo "timestamp_utc=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
- name: Setup SSH agent
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.VPS_SSH_KEY }}
- name: Add VPS host to known_hosts
run: |
mkdir -p ~/.ssh
ssh-keyscan -H ${{ secrets.VPS_HOST }} >> ~/.ssh/known_hosts
- name: Deploy via SSH & Get Server status
id: ssh_deploy
run: |
ssh -o StrictHostKeyChecking=no ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'EOF'
set -euo pipefail
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
cd ${{ secrets.VPS_PATH }}
git fetch origin master && git reset --hard origin/master
npm ci
npm run build
pm2 startOrReload ecosystem.config.js --env production
sleep 5
pm2 status > /tmp/pm2_status.txt
STATUS=$(pm2 jlist | jq -r '.[] | select(.name == "server-shopsifu") | .pm2_env.status')
[ "$STATUS" = "online" ] || exit 2
EOF
continue-on-error: true
- name: Collect PM2 status
if: always()
id: pm2_status
run: |
PM2_CONSOLE_OUTPUT=$(ssh -o StrictHostKeyChecking=no ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} 'cat /tmp/pm2_status.txt' || echo "Không thể lấy trạng thái PM2.")
echo "pm2_console_output<<EOF" >> $GITHUB_OUTPUT
echo "$PM2_CONSOLE_OUTPUT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Get Commit Info
id: commit_info
uses: actions/checkout@v4
with:
fetch-depth: 0
- run: |
COMMIT_MESSAGE=$(git log -1 --pretty=%B)
echo "commit_message<<EOF" >> $GITHUB_OUTPUT
echo "$COMMIT_MESSAGE" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
id: get_commit_message
- name: Send Discord Notification
if: always()
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
STATUS: ${{ job.status }}
BRANCH: ${{ github.ref_name }}
COMMIT: ${{ github.sha }}
ACTOR: ${{ github.actor }}
REPO: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
PM2_STATUS_OUTPUT: ${{ steps.pm2_status.outputs.pm2_console_output }}
COMMIT_MESSAGE: ${{ steps.get_commit_message.outputs.commit_message }}
JOB_STARTED_AT: ${{ steps.start_time.outputs.timestamp_utc }}
run: |
sudo apt-get update && sudo apt-get install -y jq
COLOR=$([ "$STATUS" = "success" ] && echo 3066993 || echo 15158332)
ICON=$([ "$STATUS" = "success" ] && echo "✅" || echo "❌")
STARTED_AT_EPOCH=$(date -d "$JOB_STARTED_AT" +%s)
JSON_PAYLOAD=$(jq -n \
--arg status "$STATUS" \
--arg icon "$ICON" \
--arg branch "$BRANCH" \
--arg commit_short "$(echo $COMMIT | cut -c1-7)" \
--arg commit_full "$COMMIT" \
--arg commit_message "$COMMIT_MESSAGE" \
--arg repo "$REPO" \
--arg actor "$ACTOR" \
--arg pm2_status "${PM2_STATUS_OUTPUT:0:1800}" \
--arg run_id "$RUN_ID" \
--arg color "$COLOR" \
--arg started_at "$STARTED_AT_EPOCH" \
'{
embeds: [{
title: "🚀 SERVER - Thông báo triển khai ✨",
color: ($color | tonumber),
fields: [
{ name: "Trạng thái", value: "\($icon) \($status | ascii_upcase)", inline: true },
{ name: "Nhánh", value: "`\($branch)`", inline: true },
{ name: "Người thực hiện", value: "`\($actor)`", inline: true },
{ name: "Commit", value: "[`\($commit_short)`](https://github.com/\($repo)/commit/\($commit_full))", inline: false },
{ name: "Nội dung Commit", value: "```\n\($commit_message)\n```", inline: false },
{ name: "Thời gian", value: "<t:\($started_at):R>", inline: true }
],
description: "**Trạng thái PM2 trên server:**\n```ansi\n\($pm2_status)\n```",
url: "https://github.com/\($repo)/actions/runs/\($run_id)",
"timestamp": (now | strftime("%Y-%m-%dT%H:%M:%SZ"))
}]
}')
curl -s -H "Content-Type: application/json" -X POST -d "$JSON_PAYLOAD" "$DISCORD_WEBHOOK" || echo "Lỗi gửi thông báo Discord"
# Các job rollback vẫn được giữ lại để đảm bảo an toàn
rollback-auto:
name: Automatic Rollback
needs: deploy
runs-on: ubuntu-latest
if: failure()
steps:
- name: Rollback to previous commit
run: |
ssh -o StrictHostKeyChecking=no ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'EOF'
set -euo pipefail
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
cd ${{ secrets.VPS_PATH }}
git fetch origin master && git reset --hard HEAD~1
npm ci
npm run build
pm2 startOrReload ecosystem.config.js --env production
EOF
manual-rollback:
name: Manual Rollback
if: github.event_name == 'workflow_dispatch' && github.event.inputs.manual_rollback
runs-on: ubuntu-latest
steps:
- name: Re-deploy to VPS
run: |
ssh -o StrictHostKeyChecking=no ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << 'EOF'
set -euo pipefail
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
cd ${{ secrets.VPS_PATH }}
git fetch --all
git reset --hard ${{ github.event.inputs.manual_rollback }}
npm ci
npm run build
pm2 startOrReload ecosystem.config.js --env production
EOF