Files
sanguo_moziplus_v2/docs/design/14-toolchain-skill-and-deploy.md
T
cfdaily 8e7361dbba
Deploy / ci (push) Waiting to run
Deploy / deploy (push) Blocked by required conditions
Deploy / notify-deploy-failure (push) Blocked by required conditions
auto-sync: 2026-06-08 12:49:11
2026-06-08 12:49:11 +08:00

566 lines
18 KiB
Markdown
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.
# 工具链 Skill 设计 + 自动部署 + 端到端验证
> **状态**: v1.0-draft
> **作者**: 庞统(副军师)🐦
> **评审**: 司马懿(仲达)🗡️
> **日期**: 2026-06-08
> **前置**: `13-toolchain-and-dev-workflow.md` v2.2(事件中枢已闭环)
> **定位**: 工具链从"设计完成"到"正式投入使用"的落地设计
---
## §1. 目标
把工具链从设计态推进到可使用态:
1. **L1 TOOLS.md**:每个 Agent 的 TOOLS.md 加入 Gitea API 操作模板,收到 Mail 后开箱即用
2. **L2 Skill 升级**:7 个现有 Skill 对齐事件中枢 + CI 实际运行
3. **deploy.sh + deploy.yml**:补完自动部署的实际脚本
4. **端到端验证**:用 sanguo/moziplus-v2 实验项目验证全链路
---
## §2. 知识体系四层定位
> 来源: `architecture-v3.0.md` §10 BootstrapBuilder
| 层 | 定位 | 载体 | Token | 工具链职责 |
|----|------|------|-------|-----------|
| **L0** | 铁律层 | AGENTS.md / MEMORY.md | ~500 | 不涉及 |
| **L1** | 角色层 | SOUL.md + **TOOLS.md** | ~2000 | **Gitea API 操作模板**Agent 自带,开箱即用) |
| **L2** | 引擎注入 | BootstrapBuilder 注入 Skill 全文 | ~1500 | **7 个 Skill v2**(流程规范,Daemon 确定性注入) |
| **L3** | 被动参考 | Skill descriptionAgent 按需加载 | 按需 | 复用 L2 Skill,不新建 |
**核心原则**
- L1 给操作手段("怎么做"):curl 命令模板、参数说明
- L2 给流程规范("什么时候做什么"):审查清单、分支规范、测试策略
- L3 是 L2 的被动触发版本,不需要单独维护
---
## §3. L1TOOLS.md Gitea 操作模板
### 3.1 设计原则
1. **开箱即用**:收到 Mail 后直接复制粘贴 curl 命令即可执行,不需要查文档
2. **按角色定制**:不是每个 Agent 都需要全套 API,只给该角色需要的
3. **统一格式**:所有模板使用相同的环境变量约定
### 3.2 公共变量约定
每个 Agent 的 TOOLS.md 头部加入:
```markdown
## Gitea 工具链
- **地址**: http://192.168.2.154:3000
- **组织**: sanguo
- **认证**: `Authorization: token $GITEA_TOKEN`(各 Agent 使用自己的 token
- **CI 管理界面**: http://192.168.2.154:3000/sanguo/{repo}/actions
```
### 3.3 按角色模板
#### A. 开发者(张飞/关羽/赵云)— PR 创建 + Merge
```markdown
### 创建 PR
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"head": "{branch}",
"base": "main",
"title": "{标题}"
}'
# 返回 .number 即 PR 号
```
### 查看 PR diff
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}.diff" \
-H "Authorization: token $GITEA_TOKEN"
```
### Merge PRReview 通过后)
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}/merge" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"Do": "merge", "merge_title_field": "Merge PR #{pr_number}"}'
```
### 查看 CI 状态
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/commits/{sha}/status" \
-H "Authorization: token $GITEA_TOKEN"
# .state = "success" | "pending" | "failure" | "error"
```
```
#### B. 审查者(司马懿)— Review 操作
```markdown
### 读取 PR diff
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}.diff" \
-H "Authorization: token $GITEA_TOKEN"
```
### 查看 PR 改动文件列表
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}/files" \
-H "Authorization: token $GITEA_TOKEN"
# 每个文件有 .filename, .additions, .deletions, .changes
```
### 提交 Review
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls/{pr_number}/reviews" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"body": "{审查意见}",
"event": "APPROVE"
}'
# event 可选: APPROVE | REQUEST_CHANGES | COMMENT
```
### 风险级别判定(自动 + 确认)
规则见 code-review Skill。改动者不能降级,只能维持或升级。
```
#### C. 协调者(庞统)— 全套管理
```markdown
### 创建 Issue + 指派
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/issues" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "{标题}",
"body": "{描述}",
"assignees": ["{agent_id}"],
"labels": [1, 2]
}'
# labels 需用数字 ID,先 GET /repos/{owner}/{repo}/labels 查询
```
### 查询仓库 Labels
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/labels" \
-H "Authorization: token $GITEA_TOKEN"
```
### 查询 PR 列表
```bash
curl "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/pulls?state=open" \
-H "Authorization: token $GITEA_TOKEN"
```
### 创建 Release
```bash
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/releases" \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tag_name": "v{version}",
"name": "v{version}",
"body": "{changelog}",
"target_commitish": "main"
}'
```
```
#### D. 平台运维(姜维)— deploy + runner 管理
在开发者模板基础上追加:
```markdown
### 触发手动部署(需要 push 到 main 或手动 re-run
```bash
# Re-run 最近一次 workflow
curl -X POST "http://192.168.2.154:3000/api/v1/repos/sanguo/{repo}/actions/runs/{run_id}/rerun" \
-H "Authorization: token $GITEA_TOKEN"
```
### 查看 deploy-history
```bash
cat ~/.sanguo_projects/{project}/data/deploy-history.jsonl
```
### deploy.sh 规范
见 §5 deploy.sh 设计。所有项目必须遵循统一接口。
```
### 3.4 实施清单
| Agent | TOOLS.md 新增 | 预计行数 |
|-------|--------------|---------|
| zhangfei-dev | 开发者模板(PR/Merge/CI状态) | ~30 行 |
| guanyu-dev | 开发者模板 | ~30 行 |
| zhaoyun-data | 开发者模板 | ~30 行 |
| simayi-challenger | 审查者模板(diff/review/风险判定) | ~40 行 |
| pangtong-fujunshi | 协调者模板(全套管理) | ~50 行 |
| jiangwei-infra | 开发者 + 平台运维模板 | ~45 行 |
---
## §4. L2Skill 升级到 v2
### 4.1 升级原则
1. **不重写已有内容**,在现有 Skill 基础上追加/修改
2. **对齐事件中枢**:每个 Skill 说明在事件中枢链路中的位置
3. **对齐 CI 实际运行**ci.yml/deploy.yml 已有实际配置,Skill 要反映真实情况
4. **对齐 Gitea v1.23.4 限制**:不支持 failure()、concurrency、permissions 等
### 4.2 升级内容
#### git-workflow(小改动)
| 改动 | 说明 |
|------|------|
| 追加"事件中枢集成"节 | PR 创建 → Gitea Webhook → 中枢通知司马懿 → Review → 中枢通知作者 → Merge → deploy.yml 自动触发 |
| 追加"CI 自动触发"说明 | push 非 main 分支自动触发 ci.ymlpush main 自动触发 deploy.yml |
| 追加"分支感知"强化 | Agent spawn 后必须 `git branch --show-current`,确认分支正确 |
#### code-review(中等改动)
| 改动 | 说明 |
|------|------|
| 追加"事件中枢触发"节 | 收到 Mail → 读 PR diff → 审查 → 提交 Review → Webhook 自动通知作者 |
| 更新风险判定规则 | 对齐 §6.1 实际规则(按文件路径自动判定 + 只升不降) |
| 追加 Gitea Review API 操作 | curl 模板(和 L1 TOOLS.md 一致,这里放流程说明) |
| 追加审查结论格式 | APPROVE / REQUEST_CHANGES 的标准格式 |
#### testing-workflow(小改动)
| 改动 | 说明 |
|------|------|
| 追加"CI 集成"节 | UT 在 CI 自动跑(ci.yml test job)、coverage 在 deploy.yml ci job 跑 |
| 追加"E2E 触发方式" | 通过 e2e.yml 手动触发或 `RUN_INTEGRATION=1 pytest` 本地跑 |
| 追加"测试数据隔离" | CI 使用临时 venv + 临时 SQLite + 临时端口 |
#### bugfix-workflow(小改动)
| 改动 | 说明 |
|------|------|
| 追加"事件中枢链路"节 | Bug Issue 创建/指派 → 中枢发 Mail → 修复 → PR → CI → Review → merge |
| 追加"CI 验证"步骤 | 修复后必须等 CI 通过再创建 PR |
#### hotfix-workflow(小改动)
| 改动 | 说明 |
|------|------|
| 追加"CI 自动跑"说明 | hotfix push main → deploy.yml 自动跑 CI + 部署 |
| 追加"失败自动创建 Issue" | deploy.yml notify-on-failure 已实现 |
| 更新 24h 复盘流程 | 复盘结论写到 Issue 评论中 |
#### ci-cd-ops(重写)
| 改动 | 说明 |
|------|------|
| 重写为 v2 | 对齐实际 ci.yml/deploy.yml 结构 |
| 新增 Gitea v1.23.4 限制清单 | 不支持 failure()/concurrency/permissions 等,workaround 方案 |
| 新增覆盖率渐进策略 | P1 只报告 → P2 40% 阈值 → P3 60% 阈值 |
| 新增 deploy.sh 规范 | 统一接口:--version / --source / --target / --health-check / --rollback |
| 新增 CI secret 配置 | CI_TOKEN 作为 repository secret 配置 |
#### release-workflow(中等改动)
| 改动 | 说明 |
|------|------|
| 追加"自动部署触发" | tag 创建 → deploy.yml 自动触发 |
| 追加 deploy-history.jsonl 规范 | 每次 deploy 记录 tag + commit + 时间戳 |
| 更新 schema 变更规范 | 向前兼容 Checklist(加列不加删、默认值、迁移脚本) |
### 4.3 不新建 Skill
现有 7 个 Skill 覆盖所有工具链流程。不需要为事件中枢、CI 操作新建 Skill——这些流程固化在 Mail 模板(§15.5)中,Skill 只提供共通知能。
### 4.4 实施清单
| Skill | 改动级别 | 预计改动行数 |
|-------|---------|------------|
| git-workflow | 小 | +15 行 |
| code-review | 中 | +40 行 |
| testing-workflow | 小 | +20 行 |
| bugfix-workflow | 小 | +15 行 |
| hotfix-workflow | 小 | +15 行 |
| ci-cd-ops | 重写 | ~120 行(原 114 行) |
| release-workflow | 中 | +30 行 |
---
## §5. deploy.sh + deploy.yml 补完
### 5.1 deploy.sh 统一接口
每个项目的 `scripts/deploy.sh` 必须遵循以下接口:
```bash
#!/bin/bash
# scripts/deploy.sh — 项目部署脚本
# 用法:
# bash scripts/deploy.sh --version # 显示当前版本
# bash scripts/deploy.sh --source=DIR --target=DIR --health-check # 部署
# bash scripts/deploy.sh --rollback # 回滚到上一版本
set -euo pipefail
SOURCE_DIR=""
TARGET_DIR=""
HEALTH_CHECK=false
ACTION="deploy"
for arg in "$@"; do
case $arg in
--version) ACTION="version" ;;
--source=*) SOURCE_DIR="${arg#*=}" ;;
--target=*) TARGET_DIR="${arg#*=}" ;;
--health-check) HEALTH_CHECK=true ;;
--rollback) ACTION="rollback" ;;
esac
done
PROJECT_NAME="{project_name}"
DEPLOY_HISTORY="{target_dir}/data/deploy-history.jsonl"
version() {
echo "${PROJECT_NAME} deploy version: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
deploy() {
echo "=== Deploying ${PROJECT_NAME} ==="
echo "Source: ${SOURCE_DIR}"
echo "Target: ${TARGET_DIR}"
# 1. 同步文件(排除不需要部署的)
rsync -av --delete \
--exclude='.git' \
--exclude='__pycache__' \
--exclude='.venv' \
--exclude='tests' \
--exclude='docs' \
--exclude='.gitea' \
"${SOURCE_DIR}/" "${TARGET_DIR}/"
# 2. 安装依赖
if [ -f "${TARGET_DIR}/pyproject.toml" ]; then
cd "${TARGET_DIR}"
python3 -m venv .venv
.venv/bin/pip install --quiet -e ".[dev]" 2>/dev/null || \
.venv/bin/pip install --quiet -e . 2>/dev/null || true
fi
# 3. 重启服务
if command -v pm2 &>/dev/null; then
pm2 restart ${PROJECT_NAME} 2>/dev/null || true
fi
# 4. 健康检查
if [ "$HEALTH_CHECK" = true ]; then
sleep 3
curl -sf http://localhost:8083/api/health && echo " ✓" || {
echo " ✗ Health check failed!"
exit 1
}
fi
# 5. 记录版本
local commit_hash
commit_hash=$(cd "${SOURCE_DIR}" && git rev-parse --short HEAD 2>/dev/null || echo "unknown")
local timestamp
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
echo "{\"timestamp\": \"${timestamp}\", \"commit\": \"${commit_hash}\", \"source\": \"${SOURCE_DIR}\"}" >> "${DEPLOY_HISTORY}"
# 保留最近 10 条
tail -10 "${DEPLOY_HISTORY}" > "${DEPLOY_HISTORY}.tmp" && mv "${DEPLOY_HISTORY}.tmp" "${DEPLOY_HISTORY}"
echo "=== Deploy complete: ${commit_hash} at ${timestamp} ==="
}
rollback() {
if [ ! -f "${DEPLOY_HISTORY}" ]; then
echo "No deploy history, cannot rollback"
exit 1
fi
# 读取倒数第二行
local prev_line
prev_line=$(tail -2 "${DEPLOY_HISTORY}" | head -1)
local prev_commit
prev_commit=$(echo "${prev_line}" | python3 -c "import sys,json; print(json.load(sys.stdin)['commit'])" 2>/dev/null)
if [ -z "${prev_commit}" ] || [ "${prev_commit}" = "unknown" ]; then
echo "Cannot determine previous version"
exit 1
fi
echo "=== Rolling back to ${prev_commit} ==="
cd "${SOURCE_DIR}"
git checkout "${prev_commit}"
# 重新部署(不递归 rollback
deploy
}
case $ACTION in
version) version ;;
deploy) deploy ;;
rollback) rollback ;;
esac
```
### 5.2 deploy.yml 更新
替换当前 placeholder
```yaml
deploy:
runs-on: macos-arm64
needs: ci
steps:
- uses: actions/checkout@v4
- name: Deploy
env:
CI_TOKEN: ${{ secrets.CI_TOKEN }}
run: |
bash scripts/deploy.sh --source="$GITHUB_WORKSPACE" \
--target="$HOME/.sanguo_projects/sanguo_moziplus_v2" \
--health-check
- name: Rollback on failure
if: always()
env:
CI_TOKEN: ${{ secrets.CI_TOKEN }}
run: |
STATUS=$(curl -sf \
-H "Authorization: token $CI_TOKEN" \
"${{ gitea.api_url }}/repos/${{ gitea.repository }}/commits/${{ gitea.sha }}/status" \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('state',''))" 2>/dev/null || echo "")
if [ "$STATUS" != "success" ]; then
echo "Deploy failed, rolling back..."
bash scripts/deploy.sh --rollback || echo "Rollback failed, manual intervention needed"
fi
```
### 5.3 实施清单
| # | 内容 | 文件 | 说明 |
|---|------|------|------|
| D1 | 创建 deploy.sh | moziplus-v2 `scripts/deploy.sh` | 从模板创建,项目名填 sanguo_moziplus_v2 |
| D2 | 更新 deploy.yml | moziplus-v2 `.gitea/workflows/deploy.yml` | 替换 placeholder |
| D3 | 同步到 Gitea | push 到 moziplus-v2 | 触发 CI 验证 |
---
## §6. 端到端验证:sanguo/moziplus-v2 实验项目
### 6.1 为什么用实验项目
- moziplus-v2 主项目已有正式数据(黑板项目、Mail、Task),不适合做破坏性验证
- sanguo/moziplus-v2 当前是空项目(只有 README.md + .gitea/workflows),可以随意实验
### 6.2 验证场景
| 场景 | 操作 | 预期结果 |
|------|------|---------|
| **S1: CI 触发** | push 分支到实验项目 | ci.yml 自动跑 lint + test |
| **S2: PR Review 流程** | 创建 PR → 中枢 Mail → 司马懿 Review → 中枢通知作者 | 全链路 Mail 通知 |
| **S3: CI 失败通知** | push 含 lint 错误的代码 | ci.yml 失败 → 写 PR 评论 → 中枢发 Mail |
| **S4: 部署流程** | merge PR → push main | deploy.yml 自动跑 + 部署 + 健康检查 |
| **S5: Issue 指派** | 创建 Issue 并指派 | 中枢发 Mail 给被指派人 |
### 6.3 实验项目 CI 配置
从 moziplus-v2 的 ci.yml 精简,实验项目只需要基本验证:
```yaml
name: CI
on:
push:
branches: ['**', '!main']
pull_request:
types: [opened, synchronize]
jobs:
lint:
runs-on: macos-arm64
steps:
- uses: actions/checkout@v4
- run: echo "lint placeholder"
test:
runs-on: macos-arm64
needs: lint
steps:
- uses: actions/checkout@v4
- run: echo "test placeholder"
```
---
## §7. 覆盖率渐进策略
### 7.1 P1 阶段(启用后 2 周)— 只报告不阻断
**零改动**。当前 deploy.yml 的 ci job 已包含 `--cov-report=term-missing`
收集基线数据后决定 P2 阈值。
### 7.2 后续阶段(仅设计,暂不实施)
| 阶段 | 时间 | 策略 | 触发方式 |
|------|------|------|---------|
| P2 | 启用后 1 月 | 40% 阈值,低于警告不阻断 | ci.yml 加 coverage threshold check |
| P3 | 启用后 2 月+ | 60% 阈值,低于阻断 | ci.yml 加 `exit 1` |
---
## §8. 前端展示
### 8.1 Gitea 自带管理界面
Gitea v1.23.4 自带完整的 CI 管理界面:
| 功能 | URL |
|------|-----|
| CI Runs 列表 | `http://192.168.2.154:3000/sanguo/{repo}/actions` |
| 单次 Run 日志 | `http://192.168.2.154:3000/sanguo/{repo}/actions/runs/{id}` |
| PR CI Status | PR 页面自动显示 CI 状态徽章 |
| Webhook 管理 | 仓库 Settings → Webhooks |
**不需要自己做 CI 前端。**
### 8.2 moziplus v2 前端展示
工具链事件的 Mail 通知已在 moziplus v2 前端展示(Mail 列表页)。
如果未来要加,唯一值得做的是:在 moziplus 前端加一个「工具链状态」面板,聚合展示各仓库最近 CI 状态。这是 P4,不阻塞使用。
---
## §9. 实施路线
| 优先级 | 内容 | 耗时 | 前置 |
|--------|------|------|------|
| **P1** | L1 TOOLS.md6 个 Agent | 2h | 无 |
| **P1** | L2 Skill 升级(7 个) | 1d | 无 |
| **P2** | deploy.sh + deploy.yml | 2h | P1 Skill 升级(ci-cd-ops 定义了 deploy.sh 规范) |
| **P3** | sanguo/moziplus-v2 端到端验证 | 2h | P1 + P2 |
| **P4** | 前端工具链状态面板 | 按需 | 不阻塞 |
---
## §10. 评审清单
请仲达重点审查:
1. **L1 按角色分配是否合理**:开发者/审查者/协调者/运维的 API 覆盖是否完整,有无冗余
2. **L2 升级内容是否足够**:7 个 Skill 的改动是否覆盖了事件中枢集成所需的所有知识
3. **deploy.sh 设计是否完整**:接口是否统一、回滚是否可靠、健康检查是否合理
4. **验证场景是否覆盖关键路径**:S1-S5 是否覆盖了工具链的所有核心场景
5. **有没有遗漏的前置条件**:比如 Gitea secret 配置、分支保护开启等