# ═══════════════════════════════════════════════ # 🔺 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"