310 lines
11 KiB
YAML
310 lines
11 KiB
YAML
name: 🏛️ 铸渊主权服务器 · 部署
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# 铸渊主权服务器部署工作流
|
|
# 编号: ZY-WF-铸体 (新器官 · 服务器部署引擎)
|
|
# 守护: 铸渊 · ICE-GL-ZY001
|
|
# 版权: 国作登字-2026-A-00037559
|
|
# ═══════════════════════════════════════════════════════════
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'server/**'
|
|
workflow_dispatch:
|
|
inputs:
|
|
action:
|
|
description: '部署动作'
|
|
required: true
|
|
default: 'deploy'
|
|
type: choice
|
|
options:
|
|
- deploy
|
|
- init
|
|
- health-check
|
|
- promote
|
|
deploy_target:
|
|
description: '部署目标站点'
|
|
required: false
|
|
default: 'preview'
|
|
type: choice
|
|
options:
|
|
- preview
|
|
- production
|
|
|
|
concurrency:
|
|
group: zhuyuan-server-deploy
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
# ═══ §1 初始化 (仅首次) ═══
|
|
init:
|
|
name: 🔧 服务器初始化
|
|
if: github.event.inputs.action == 'init'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 🔐 配置SSH
|
|
run: |
|
|
mkdir -p ~/.ssh
|
|
# 写入私钥(支持多种格式)
|
|
printf '%s\n' "${{ secrets.ZY_SERVER_KEY }}" > ~/.ssh/zy_key
|
|
chmod 600 ~/.ssh/zy_key
|
|
# 验证私钥格式
|
|
if head -1 ~/.ssh/zy_key | grep -q "BEGIN"; then
|
|
echo "✅ SSH私钥格式正确"
|
|
else
|
|
echo "❌ SSH私钥格式异常 — 请检查 GitHub Secrets 中 ZY_SERVER_KEY 的内容"
|
|
echo " 应以 '-----BEGIN' 开头,以 '-----END' 结尾"
|
|
exit 1
|
|
fi
|
|
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
|
|
|
- name: 🔍 SSH连接测试
|
|
run: |
|
|
echo "🔍 测试SSH连接到 ${{ secrets.ZY_SERVER_HOST }}..."
|
|
ssh -i ~/.ssh/zy_key -o BatchMode=yes -o ConnectTimeout=10 \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \
|
|
'echo "✅ SSH连接成功 · $(hostname) · $(date)"' || {
|
|
echo ""
|
|
echo "═══════════════════════════════════════════════"
|
|
echo "❌ SSH连接失败 · 排查指南"
|
|
echo "═══════════════════════════════════════════════"
|
|
echo ""
|
|
echo "可能原因:"
|
|
echo " 1. 服务器未配置对应的SSH公钥"
|
|
echo " 2. GitHub Secrets中的私钥不完整或格式错误"
|
|
echo " 3. SSH用户名不正确"
|
|
echo ""
|
|
echo "修复步骤(冰朔操作):"
|
|
echo " ① 登录腾讯云控制台 → 轻量应用服务器 → 选择新加坡服务器"
|
|
echo " ② 点击「远程登录」→ 使用网页终端登录"
|
|
echo " ③ 在终端中执行以下命令生成新密钥:"
|
|
echo " ssh-keygen -t ed25519 -f ~/.ssh/github_deploy -N ''"
|
|
echo " cat ~/.ssh/github_deploy.pub >> ~/.ssh/authorized_keys"
|
|
echo " chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
|
|
echo " cat ~/.ssh/github_deploy"
|
|
echo " ④ 复制输出的私钥内容(从 -----BEGIN 到 -----END 完整复制)"
|
|
echo " ⑤ 打开 GitHub → Settings → Secrets → 更新 ZY_SERVER_KEY"
|
|
echo "═══════════════════════════════════════════════"
|
|
exit 1
|
|
}
|
|
|
|
- name: 📦 上传初始化脚本
|
|
run: |
|
|
scp -i ~/.ssh/zy_key \
|
|
server/setup/zhuyuan-server-init.sh \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }}:/tmp/
|
|
|
|
- name: 🚀 执行初始化
|
|
run: |
|
|
ssh -i ~/.ssh/zy_key \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \
|
|
'chmod +x /tmp/zhuyuan-server-init.sh && sudo /tmp/zhuyuan-server-init.sh'
|
|
|
|
# ═══ §2 部署应用 (默认部署到预览站) ═══
|
|
deploy:
|
|
name: 🚀 部署应用代码
|
|
if: github.event.inputs.action == 'deploy' || github.event.inputs.action == '' || github.event_name == 'push'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 🔐 配置SSH
|
|
run: |
|
|
mkdir -p ~/.ssh
|
|
printf '%s\n' "${{ secrets.ZY_SERVER_KEY }}" > ~/.ssh/zy_key
|
|
chmod 600 ~/.ssh/zy_key
|
|
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
|
run: |
|
|
# 确定部署目标: preview (默认) 或 production
|
|
TARGET="${{ github.event.inputs.deploy_target || 'preview' }}"
|
|
TARGET_DIR="/opt/zhuyuan/sites/${TARGET}"
|
|
echo "📦 部署目标: ${TARGET} → ${TARGET_DIR}"
|
|
|
|
# 确保目标目录存在
|
|
ssh -i ~/.ssh/zy_key \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \
|
|
"mkdir -p ${TARGET_DIR}"
|
|
|
|
rsync -avz --delete \
|
|
-e "ssh -i ~/.ssh/zy_key" \
|
|
server/app/ \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }}:/opt/zhuyuan/app/
|
|
|
|
- name: 📦 同步配置文件
|
|
run: |
|
|
# PM2 配置
|
|
scp -i ~/.ssh/zy_key \
|
|
server/ecosystem.config.js \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }}:/opt/zhuyuan/config/pm2/
|
|
|
|
# Nginx 配置
|
|
scp -i ~/.ssh/zy_key \
|
|
server/nginx/zhuyuan-sovereign.conf \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }}:/opt/zhuyuan/config/nginx/
|
|
|
|
- name: 📥 安装依赖 & 重启
|
|
run: |
|
|
COMMIT_SHA="${{ github.sha }}"
|
|
REF_NAME="${{ github.ref_name }}"
|
|
ssh -i ~/.ssh/zy_key \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} << DEPLOY_CMD
|
|
|
|
set -e
|
|
cd /opt/zhuyuan/app
|
|
|
|
# 安装依赖
|
|
npm install --production 2>&1
|
|
|
|
# 复制Nginx配置
|
|
sudo cp /opt/zhuyuan/config/nginx/zhuyuan-sovereign.conf /etc/nginx/sites-available/zhuyuan.conf
|
|
sudo ln -sf /etc/nginx/sites-available/zhuyuan.conf /etc/nginx/sites-enabled/zhuyuan.conf
|
|
sudo nginx -t && sudo systemctl reload nginx
|
|
|
|
# PM2 重启
|
|
pm2 delete zhuyuan-server 2>/dev/null || true
|
|
pm2 start /opt/zhuyuan/config/pm2/ecosystem.config.js
|
|
pm2 save
|
|
|
|
# 健康检查
|
|
sleep 3
|
|
curl -sf http://localhost:3800/api/health || echo "⚠️ 健康检查失败,等待更长时间..."
|
|
sleep 5
|
|
curl -sf http://localhost:3800/api/health && echo "✅ 服务器已上线" || echo "❌ 服务器启动失败"
|
|
|
|
# 记录部署操作
|
|
curl -sf -X POST http://localhost:3800/api/operations \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"operator\": \"铸渊 · GitHub Actions\",
|
|
\"action\": \"自动部署\",
|
|
\"details\": \"commit: ${COMMIT_SHA}, branch: ${REF_NAME}\"
|
|
}" || true
|
|
|
|
DEPLOY_CMD
|
|
|
|
# ═══ §3 健康检查 ═══
|
|
health-check:
|
|
name: 💚 健康检查
|
|
if: github.event.inputs.action == 'health-check'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 🔐 配置SSH
|
|
run: |
|
|
mkdir -p ~/.ssh
|
|
printf '%s\n' "${{ secrets.ZY_SERVER_KEY }}" > ~/.ssh/zy_key
|
|
chmod 600 ~/.ssh/zy_key
|
|
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
|
|
|
- name: 💚 执行健康检查
|
|
run: |
|
|
ssh -i ~/.ssh/zy_key \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} << 'HEALTH_CMD'
|
|
|
|
echo "═══ 铸渊主权服务器健康报告 ═══"
|
|
echo ""
|
|
|
|
echo "§1 系统状态:"
|
|
uptime
|
|
echo ""
|
|
|
|
echo "§2 磁盘使用:"
|
|
df -h /
|
|
echo ""
|
|
|
|
echo "§3 内存使用:"
|
|
free -m
|
|
echo ""
|
|
|
|
echo "§4 PM2 进程:"
|
|
pm2 list 2>/dev/null || echo "PM2 未运行"
|
|
echo ""
|
|
|
|
echo "§5 Nginx 状态:"
|
|
systemctl is-active nginx && echo "Nginx: 运行中" || echo "Nginx: 已停止"
|
|
echo ""
|
|
|
|
echo "§6 应用健康:"
|
|
curl -sf http://localhost:3800/api/health | jq . 2>/dev/null || echo "应用未响应"
|
|
echo ""
|
|
|
|
echo "§7 大脑状态:"
|
|
curl -sf http://localhost:3800/api/brain | jq '.files_present, .files_total' 2>/dev/null || echo "大脑API未响应"
|
|
echo ""
|
|
|
|
echo "§8 双站点状态:"
|
|
curl -sf http://localhost:3800/api/sites | jq . 2>/dev/null || echo "站点API未响应"
|
|
|
|
HEALTH_CMD
|
|
|
|
# ═══ §4 一键推送: 预览站 → 主站 ═══
|
|
promote:
|
|
name: 🚀 预览站→主站 一键推送
|
|
if: github.event.inputs.action == 'promote'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 🔐 配置SSH
|
|
run: |
|
|
mkdir -p ~/.ssh
|
|
printf '%s\n' "${{ secrets.ZY_SERVER_KEY }}" > ~/.ssh/zy_key
|
|
chmod 600 ~/.ssh/zy_key
|
|
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
|
|
|
- name: 🚀 执行推送
|
|
run: |
|
|
echo "🚀 一键推送: 预览站 → 主站"
|
|
RUN_ID="${{ github.run_id }}"
|
|
ssh -i ~/.ssh/zy_key \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} << PROMOTE_CMD
|
|
|
|
# 调用铸渊 API 执行推送
|
|
RESULT=\$(curl -sf -X POST http://localhost:3800/api/sites/promote \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"operator\": \"冰朔 · 通过 GitHub Actions 授权推送\",
|
|
\"note\": \"workflow_dispatch promote · run_id: ${RUN_ID}\"
|
|
}" 2>/dev/null)
|
|
|
|
if [ \$? -eq 0 ]; then
|
|
echo "\$RESULT" | jq . 2>/dev/null || echo "\$RESULT"
|
|
echo ""
|
|
echo "✅ 预览站已推送到主站"
|
|
else
|
|
echo "❌ 推送失败"
|
|
echo "尝试手动执行..."
|
|
if [ -d /opt/zhuyuan/sites/preview ] && [ -f /opt/zhuyuan/sites/preview/index.html ]; then
|
|
rsync -a --delete /opt/zhuyuan/sites/preview/ /opt/zhuyuan/sites/production/
|
|
echo "✅ 手动推送完成"
|
|
else
|
|
echo "❌ 预览站无内容,无法推送"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
PROMOTE_CMD
|
|
|
|
- name: 💚 推送后验证
|
|
run: |
|
|
ssh -i ~/.ssh/zy_key \
|
|
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} << 'VERIFY_CMD'
|
|
|
|
echo "═══ 推送后验证 ═══"
|
|
echo ""
|
|
echo "主站内容:"
|
|
ls -la /opt/zhuyuan/sites/production/ | head -10
|
|
echo ""
|
|
echo "站点状态:"
|
|
curl -sf http://localhost:3800/api/sites | jq . 2>/dev/null || echo "API未响应"
|
|
|
|
VERIFY_CMD
|