From 1b41e28499f72a193270b8c3678066b205b2dccc Mon Sep 17 00:00:00 2001 From: yunxiafei <307327147@qq.com> Date: Sat, 14 Mar 2026 22:27:37 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E6=96=B9=E6=A1=88=E5=88=B0=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 功能: - Gitea Webhook + 更新脚本方案 - 自动拉取代码、构建镜像、重启容器 - 健康检查确认更新成功 作者: 小白 🐶 --- README.md | 100 ++++++++++++ README.md.new | 6 + docs/AUTO_DEPLOY.md | 378 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 484 insertions(+) create mode 100644 README.md.new create mode 100644 docs/AUTO_DEPLOY.md diff --git a/README.md b/README.md index e51181c..1bf7b9d 100644 --- a/README.md +++ b/README.md @@ -631,6 +631,106 @@ volumes: --- +## 自动部署 🔄 + +> Gitea 仓库提交后自动更新 Docker 容器 + +### 方案对比 + +| 方案 | 复杂度 | 说明 | +|------|--------|------| +| **方案 1: Webhook + 脚本** | ⭐ 简单 | 推荐,实现快、依赖少 | +| **方案 2: Gitea Actions** | ⭐⭐⭐ 中等 | 功能强大,需要配置 Runner | +| **方案 3: Watchtower** | ⭐⭐ 简单 | 自动监控镜像更新 | + +### 推荐方案:Webhook + 脚本 + +#### 架构流程 + +``` +开发者推送代码 → Gitea 触发 Webhook → 更新脚本执行 + → 拉取代码 → 构建镜像 → 重启容器 → 健康检查 +``` + +#### 1. 更新脚本 + +```bash +#!/bin/bash +# /www/wwwroot/pit-router/auto-update.sh + +set -e +cd /www/wwwroot/pit-router + +# 拉取最新代码 +git fetch origin && git reset --hard origin/main + +# 重建并启动 +docker-compose down +docker-compose build --no-cache +docker-compose up -d + +# 健康检查 +sleep 10 +curl -sf http://localhost:1999/health && echo "✅ 更新成功" +``` + +#### 2. Webhook 服务 + +```python +# /www/wwwroot/pit-router/webhook-server.py + +from flask import Flask, request, jsonify +import hmac, hashlib, subprocess + +app = Flask(__name__) +SECRET = 'your-webhook-secret' + +@app.route('/webhook/pit-router', methods=['POST']) +def handle(): + # 验证签名 + sig = request.headers.get('X-Gitea-Signature', '') + expected = 'sha256=' + hmac.new(SECRET.encode(), request.data, hashlib.sha256).hexdigest() + if not hmac.compare_digest(sig, expected): + return {'error': 'Invalid signature'}, 401 + + # 执行更新 + result = subprocess.run(['/www/wwwroot/pit-router/auto-update.sh'], capture_output=True) + return {'status': 'success' if result.returncode == 0 else 'error'} + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5001) +``` + +#### 3. 配置 Gitea Webhook + +```bash +curl -X POST "http://localhost:3000/api/v1/repos/yunxiafei/pit-router/hooks" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "type": "gitea", + "config": { + "url": "http://localhost:5001/webhook/pit-router", + "content_type": "json", + "secret": "your-webhook-secret" + }, + "events": ["push"], + "active": true + }' +``` + +### 实施清单 + +- [ ] 创建 `auto-update.sh` 脚本 +- [ ] 创建 `webhook-server.py` 服务 +- [ ] 配置 systemd 服务 +- [ ] 配置 Gitea Webhook +- [ ] 测试自动更新 + +**预计时间**:30 分钟 + +--- + ## 相关项目 - [PIT Channel 插件](http://1.14.58.157:3000/yunxiafei/PIT_Channel) - OpenClaw Channel 插件(智队中枢客户端) diff --git a/README.md.new b/README.md.new new file mode 100644 index 0000000..b96ab4e --- /dev/null +++ b/README.md.new @@ -0,0 +1,6 @@ +# 智队中枢(PIT Router) + +> PIT 网关路由应用 - Personal Intelligent Team Gateway Router Service + +**中文名**:智队中枢 +**英文名**:PIT Router diff --git a/docs/AUTO_DEPLOY.md b/docs/AUTO_DEPLOY.md new file mode 100644 index 0000000..9a5d084 --- /dev/null +++ b/docs/AUTO_DEPLOY.md @@ -0,0 +1,378 @@ +# 智队中枢 - 自动部署方案 + +> Gitea 仓库提交后自动更新 Docker 容器 + +## 📋 方案对比 + +| 方案 | 复杂度 | 优点 | 缺点 | +|------|--------|------|------| +| **方案 1: Webhook + 脚本** | ⭐ 简单 | 实现快、依赖少 | 功能单一 | +| **方案 2: Gitea Actions** | ⭐⭐⭐ 中等 | 功能强大、可扩展 | 需要配置 Runner | +| **方案 3: Watchtower** | ⭐⭐ 简单 | 自动化程度高 | 需要镜像仓库 | + +**推荐方案**:方案 1(Webhook + 脚本)+ 方案 3(Watchtower)组合 + +--- + +## 🚀 方案 1: Gitea Webhook + 更新脚本 + +### 架构流程 + +``` +开发者推送代码 + ↓ +Gitea 仓库接收推送 + ↓ +触发 Webhook (push 事件) + ↓ +Webhook 服务接收请求 + ↓ +验证签名 + 执行更新脚本 + ↓ +拉取最新代码 → 构建镜像 → 重启容器 + ↓ +发送通知(可选) +``` + +### 实现步骤 + +#### 1. 创建更新脚本 + +```bash +#!/bin/bash +# /www/wwwroot/pit-router/auto-update.sh + +set -e + +LOG_FILE="/var/log/pit-router-update.log" +REPO_DIR="/www/wwwroot/pit-router" + +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +log "========== 开始自动更新 ==========" + +cd "$REPO_DIR" + +# 1. 拉取最新代码 +log "拉取最新代码..." +git fetch origin +git reset --hard origin/main + +# 2. 停止旧容器 +log "停止旧容器..." +docker-compose down + +# 3. 构建新镜像 +log "构建新镜像..." +docker-compose build --no-cache + +# 4. 启动新容器 +log "启动新容器..." +docker-compose up -d + +# 5. 等待健康检查 +log "等待服务启动..." +sleep 10 + +# 6. 健康检查 +if curl -sf http://localhost:1999/health > /dev/null; then + log "✅ 更新成功!服务运行正常" +else + log "❌ 更新失败!服务未正常启动" + exit 1 +fi + +log "========== 更新完成 ==========" +``` + +#### 2. 创建 Webhook 服务 + +```python +# /www/wwwroot/pit-router/webhook-server.py + +from flask import Flask, request, jsonify +import hmac +import hashlib +import subprocess +import os + +app = Flask(__name__) + +# 配置 +WEBHOOK_SECRET = os.environ.get('WEBHOOK_SECRET', 'your-webhook-secret') +UPDATE_SCRIPT = '/www/wwwroot/pit-router/auto-update.sh' + +def verify_signature(payload, signature): + """验证 Webhook 签名""" + expected = 'sha256=' + hmac.new( + WEBHOOK_SECRET.encode(), + payload, + hashlib.sha256 + ).hexdigest() + return hmac.compare_digest(expected, signature) + +@app.route('/webhook/pit-router', methods=['POST']) +def handle_webhook(): + """处理 Gitea Webhook""" + # 验证签名 + signature = request.headers.get('X-Gitea-Signature', '') + if not verify_signature(request.data, signature): + return jsonify({'error': 'Invalid signature'}), 401 + + # 解析事件 + event = request.headers.get('X-Gitea-Event', '') + if event != 'push': + return jsonify({'message': 'Event ignored'}), 200 + + data = request.json + ref = data.get('ref', '') + + # 只处理 main 分支 + if ref != 'refs/heads/main': + return jsonify({'message': 'Branch ignored'}), 200 + + # 执行更新脚本 + try: + result = subprocess.run( + [UPDATE_SCRIPT], + capture_output=True, + text=True, + timeout=300 + ) + + if result.returncode == 0: + return jsonify({ + 'status': 'success', + 'message': 'Update completed', + 'output': result.stdout + }) + else: + return jsonify({ + 'status': 'error', + 'message': result.stderr + }), 500 + + except subprocess.TimeoutExpired: + return jsonify({'error': 'Update timeout'}), 500 + except Exception as e: + return jsonify({'error': str(e)}), 500 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5001) +``` + +#### 3. 创建 systemd 服务 + +```ini +# /etc/systemd/system/pit-router-webhook.service + +[Unit] +Description=PIT Router Webhook Server +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/www/wwwroot/pit-router +Environment=WEBHOOK_SECRET=your-webhook-secret +ExecStart=/usr/bin/python3 /www/wwwroot/pit-router/webhook-server.py +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +#### 4. 配置 Gitea Webhook + +```bash +TOKEN="509149b911143135084d20c44fc97a462a16945a" + +# 创建 Webhook +curl -X POST "http://localhost:3000/api/v1/repos/yunxiafei/pit-router/hooks" \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "type": "gitea", + "config": { + "url": "http://localhost:5001/webhook/pit-router", + "content_type": "json", + "secret": "your-webhook-secret" + }, + "events": ["push"], + "active": true + }' +``` + +--- + +## 🔄 方案 2: Gitea Actions(推荐用于复杂项目) + +### 架构流程 + +``` +开发者推送代码 + ↓ +Gitea Actions 触发 + ↓ +Runner 执行工作流 + ↓ +构建 → 测试 → 推送镜像 → 部署 + ↓ +通知结果 +``` + +### 工作流配置 + +```yaml +# .gitea/workflows/deploy.yml + +name: Build and Deploy + +on: + push: + branches: [main] + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker + uses: docker/setup-buildx-action@v3 + + - name: Build Image + run: | + docker build -t pit-router:latest . + + - name: Run Tests + run: | + docker run --rm pit-router:latest python -m pytest tests/ + + - name: Deploy + run: | + docker-compose down + docker-compose up -d + + - name: Health Check + run: | + sleep 10 + curl -sf http://localhost:1999/health || exit 1 +``` + +### 配置 Gitea Actions Runner + +```bash +# 创建 Runner Token +TOKEN="509149b911143135084d20c44fc97a462a16945a" + +curl -X POST "http://localhost:3000/api/v1/admin/runners/registration-token" \ + -H "Authorization: token $TOKEN" + +# 安装 Runner +docker run -d \ + --name gitea-runner \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /www/wwwroot/pit-router:/workspace \ + -e GITEA_INSTANCE_URL=http://localhost:3000 \ + -e GITEA_RUNNER_REGISTRATION_TOKEN= \ + gitea/act_runner:latest +``` + +--- + +## 📦 方案 3: Watchtower(自动监控镜像更新) + +### 适用场景 + +适用于已经推送到镜像仓库的场景。 + +### 配置 + +```yaml +# docker-compose.yaml 添加 watchtower + + watchtower: + image: containrrr/watchtower + volumes: + - /var/run/docker.sock:/var/run/docker.sock + environment: + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_POLL_INTERVAL=300 # 每 5 分钟检查一次 + - WATCHTOWER_NOTIFICATIONS=email + - WATCHTOWER_NOTIFICATION_EMAIL_FROM=alert@example.com + - WATCHTOWER_NOTIFICATION_EMAIL_TO=admin@example.com + - WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.example.com + restart: unless-stopped +``` + +--- + +## 🎯 推荐方案 + +### 简单场景(当前推荐) + +**方案 1: Webhook + 脚本** + +| 项目 | 说明 | +|------|------| +| 复杂度 | 低 | +| 依赖 | Flask + 简单脚本 | +| 部署时间 | 30 分钟 | +| 维护成本 | 低 | + +### 复杂场景(未来扩展) + +**方案 2: Gitea Actions** + +| 项目 | 说明 | +|------|------| +| 复杂度 | 中 | +| 依赖 | Gitea Runner | +| 功能 | 测试、构建、部署一体化 | +| 维护成本 | 中 | + +--- + +## 📝 实施清单 + +### 方案 1 实施步骤 + +- [ ] 创建更新脚本 `auto-update.sh` +- [ ] 创建 Webhook 服务 `webhook-server.py` +- [ ] 创建 systemd 服务 +- [ ] 配置 Gitea Webhook +- [ ] 测试自动更新流程 + +### 预计时间 + +- 首次部署:30 分钟 +- 后续维护:几乎无 + +--- + +## ⚠️ 注意事项 + +1. **安全性** + - Webhook 必须验证签名 + - 限制 Webhook 访问来源 IP + - 敏感信息使用环境变量 + +2. **可靠性** + - 更新失败自动回滚 + - 健康检查确认成功 + - 日志记录完整 + +3. **生产环境** + - 考虑蓝绿部署 + - 考虑金丝雀发布 + - 监控告警 + +--- + +*文档版本: v1.0 | 创建时间: 2026-03-14 | 作者: 小白 🐶*