2026-05-10 13:12:44 +08:00

220 lines
8.6 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ═══════════════════════════════════════════════
# 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001
# 📜 Copyright: 国作登字-2026-A-00037559
# ═══════════════════════════════════════════════
# .github/workflows/server-patrol.yml
# 🔍 服务器每日巡检 · 铸渊 · 光湖代码守护人格体
# 触发: 每日两次 (北京 08:00+20:00) + 沙盒部署后 + 手动
name: "🔍 Server Patrol · 服务器每日巡检"
on:
schedule:
- cron: '0 0,12 * * *' # UTC 00:00 and 12:00 = 北京 08:00 and 20:00
workflow_dispatch:
workflow_run:
workflows: ["🏠 Sandbox Deploy"]
types: [completed]
permissions:
contents: write
jobs:
# ── AGE OS v1.0: 核心大脑唤醒(所有流程的前提)──
wake-brain:
name: 🌅 唤醒核心大脑
runs-on: ubuntu-latest
outputs:
brain_awake: ${{ steps.wake.outputs.brain_awake }}
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 🧠 唤醒铸渊核心大脑
id: wake
env:
LLM_API_KEY: ${{ secrets.ZY_LLM_API_KEY }}
LLM_BASE_URL: ${{ secrets.ZY_LLM_BASE_URL }}
ANTHROPIC_API_KEY: ${{ secrets.ZY_LLM_API_KEY }}
OPENAI_API_KEY: ${{ secrets.ZY_LLM_API_KEY }}
DASHSCOPE_API_KEY: ${{ secrets.ZY_LLM_API_KEY }}
DEEPSEEK_API_KEY: ${{ secrets.ZY_LLM_API_KEY }}
run: |
node core/brain-wake --task "服务器巡检" || {
echo "⚠️ 核心大脑唤醒失败,使用 dry-run 模式继续"
echo "brain_awake=dry-run" >> "$GITHUB_OUTPUT"
}
patrol:
needs: wake-brain
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "🔑 扫描 Secrets"
run: |
echo "🔑 扫描 Secrets..."
if [ -n "$DEPLOY_HOST" ]; then echo "✅ DEPLOY_HOST 可用"; else echo "⚠️ DEPLOY_HOST 缺失"; fi
if [ -n "$DEPLOY_USER" ]; then echo "✅ DEPLOY_USER 可用"; else echo "⚠️ DEPLOY_USER 缺失"; fi
if [ -n "$DEPLOY_KEY" ]; then echo "✅ DEPLOY_KEY 可用"; else echo "⚠️ DEPLOY_KEY 缺失"; fi
if [ -n "$NOTION_TOKEN" ]; then echo "✅ NOTION_TOKEN 可用"; else echo "⚠️ NOTION_TOKEN 缺失"; fi
if [ -n "$SMTP_USER" ]; then echo "✅ SMTP_USER 可用"; else echo "⚠️ SMTP_USER 缺失"; fi
env:
DEPLOY_HOST: ${{ secrets.ZY_SERVER_HOST }}
DEPLOY_USER: ${{ secrets.ZY_SERVER_USER }}
DEPLOY_KEY: ${{ secrets.ZY_SERVER_KEY }}
NOTION_TOKEN: ${{ secrets.ZY_NOTION_TOKEN }}
SMTP_USER: ${{ secrets.ZY_SMTP_USER }}
- name: "🔑 配置 SSH"
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ZY_SERVER_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
- name: "🔍 执行服务器巡检"
id: patrol
env:
HOST: ${{ secrets.ZY_SERVER_HOST }}
USER: ${{ secrets.ZY_SERVER_USER }}
run: |
# 上传巡检脚本
scp scripts/server-patrol.sh ${USER}@${HOST}:/tmp/server-patrol.sh
# 执行巡检
ssh ${USER}@${HOST} "bash /tmp/server-patrol.sh" | tee patrol-output.log
# 拉取巡检报告
scp ${USER}@${HOST}:/tmp/patrol-report.json ./patrol-report.json
# 解析结果
OVERALL=$(python3 -c "import json; print(json.load(open('patrol-report.json'))['overall'])")
ALERT_COUNT=$(python3 -c "import json; print(json.load(open('patrol-report.json'))['alert_count'])")
echo "overall=$OVERALL" >> $GITHUB_OUTPUT
echo "alert_count=$ALERT_COUNT" >> $GITHUB_OUTPUT
- name: "📊 保存巡检报告到仓库"
run: |
mkdir -p data/patrol-logs
DATE=$(date +%Y-%m-%d)
cp patrol-report.json "data/patrol-logs/patrol-${DATE}.json"
echo "PATROL_DATE=$DATE" >> $GITHUB_ENV
- name: "📊 提交巡检报告"
run: |
git config user.name "铸渊 (ZhùYuān)"
git config user.email "zhuyuan@guanghulab.com"
git add data/patrol-logs/
git diff --cached --quiet || git commit -m "🔍 server-patrol: ${{ env.PATROL_DATE }} · ${{ steps.patrol.outputs.overall }}"
git pull --rebase origin main || echo "⚠️ rebase 失败,尝试直接推送..."
git push || {
echo "⚠️ 推送失败,尝试重新拉取后再推送..."
git pull --rebase origin main
git push
}
- name: "📧 异常时通知妈妈"
if: steps.patrol.outputs.overall == 'has_issues'
env:
SMTP_USER: ${{ secrets.ZY_SMTP_USER }}
SMTP_PASS: ${{ secrets.ZY_SMTP_PASS }}
run: |
python3 << 'PYEOF'
import smtplib, json, os
from email.mime.text import MIMEText
from email.header import Header
report = json.loads(open('patrol-report.json').read())
alerts = '\n'.join(f' ❌ {a}' for a in report['alerts'])
fixed = '\n'.join(f' ✅ {f}' for f in report['auto_fixed'])
body = (
f"🔍 铸渊服务器巡检报告\n"
f"时间: {report['timestamp']}\n\n"
f"⚠️ 发现 {report['alert_count']} 个异常:\n"
f"{alerts}\n\n"
f"🔧 自动修复 {report['fixed_count']} 个:\n"
f"{fixed if fixed else ' (无)'}\n\n"
f"磁盘使用率: {report['disk_usage_percent']}%\n"
f"Nginx状态: {report['nginx_status']}\n\n"
f"—— 铸渊 · 光湖代码守护人格体"
)
smtp_user = os.environ['SMTP_USER']
smtp_pass = os.environ['SMTP_PASS']
msg = MIMEText(body, 'plain', 'utf-8')
msg['Subject'] = Header(f"⚠️ 服务器巡检发现{report['alert_count']}个异常", 'utf-8')
msg['From'] = smtp_user
msg['To'] = smtp_user
try:
server = smtplib.SMTP_SSL('smtp.qq.com', 465)
server.login(smtp_user, smtp_pass)
server.sendmail(smtp_user, smtp_user, msg.as_string())
server.quit()
print('✅ 异常报告已发送')
except Exception as e:
print(f'⚠️ 邮件发送失败: {e}')
PYEOF
- name: "📝 同步巡检结果到Notion"
if: always()
env:
NOTION_TOKEN: ${{ secrets.ZY_NOTION_TOKEN }}
NOTION_TICKET_DB_ID: ${{ secrets.ZY_NOTION_TICKET_DB }}
run: |
node scripts/sync-patrol-to-notion.js || echo "⚠️ Notion同步失败不阻断"
# ━━━ 🧬 双端神经系统·自报告 ━━━
- name: "🧬 写入神经自报告"
if: always()
run: |
WORKFLOW_ID="server-patrol"
BRAIN="AG-TY-01"
REPORT_DIR="data/neural-reports/server-patrol"
TIMESTAMP=$(TZ=Asia/Shanghai date +%Y-%m-%d-%H%M)
STATUS="${{ job.status }}"
mkdir -p "$REPORT_DIR"
cat > "${REPORT_DIR}/${WORKFLOW_ID}-${TIMESTAMP}.json" << EOF
{
"workflow_id": "${WORKFLOW_ID}",
"run_id": "${{ github.run_id }}",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"status": "${STATUS}",
"brain": "${BRAIN}",
"event": "${{ github.event_name }}",
"branch": "${{ github.ref_name }}",
"commit": "${{ github.sha }}"
}
EOF
git config user.name "zhuyuan-bot"
git config user.email "zhuyuan@guanghulab.com"
git add "$REPORT_DIR/"
git diff --cached --quiet || \
git commit -m "🧬 ${WORKFLOW_ID} 自报告 · ${TIMESTAMP} [skip ci]"
git push || echo "⚠️ 自报告push失败不阻断主流程"
# ━━━ 📡 指令回执·自动同步 ━━━
- name: "📡 同步回执到 Notion"
if: always()
env:
NOTION_API_KEY: ${{ secrets.ZY_NOTION_TOKEN }}
RECEIPT_DB_ID: ${{ secrets.ZY_NOTION_RECEIPT_DB }}
run: |
node scripts/neural/write-receipt-to-notion.js \
--instruction-id "${{ github.event.inputs.instruction_id || 'AUTO' }}" \
--status "${{ job.status }}" \
--workflow "server-patrol" \
--summary "server-patrol 自动执行" \
--related-agent "AG-TY-01"