从 "人肉 Review" 到 "AI 自动审查":让代码规范落地不再依赖个人自觉
一、背景:为什么需要自动化代码审查?
1.1 团队痛点
在快节奏的敏捷开发中,代码审查(Code Review)往往面临以下困境:
- 审查流于形式:人工 Review 容易遗漏细节,尤其是风格问题和安全隐患
- 规范难以落地:团队有 ESLint/Prettier 配置,但开发者经常绕过或忽略
- 跨域引用失控:Feature 之间直接 import,导致架构边界模糊,"意大利面条"代码滋生
- 安全问题后置:硬编码 Token、XSS 漏洞等问题在上线前才被发现,修复成本极高
- 审查效率低下:重复性的风格审查往往会占用大量的review时间
1.2 传统方案的局限
| 方案 | 问题 |
|---|---|
| 纯 ESLint/Prettier | 只能检查语法风格,无法审查架构设计、业务逻辑 |
| GitHub Actions | 需要维护 CI 流水线,配置复杂,反馈链路长 |
| 人工 Code Review | 依赖个人经验,标准不统一,容易遗漏 |
1.3 OpenClaw 的独特优势
OpenClaw 是一个开源的 AI Agent 框架,支持:
- Webhook 驱动:实时响应 GitHub Push/PR 事件
- AI 智能分析:基于自定义规则库进行深度代码分析
- 即时通知:通过钉钉/飞书/Slack 等渠道快速反馈
- 规则可扩展:支持项目特定的架构规范(如 Feature-First 分层)
本文将介绍如何基于 OpenClaw 构建一套贴合团队规范的自动化代码审查系统。
二、整体流程设计
2.1 系统架构
┌─────────────┐ Push Event ┌──────────────┐
│ GitHub │ ──────────────────> │ OpenClaw │
│ Repository │ │ Gateway │
└─────────────┘ └──────┬───────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 安全扫描 │ │架构审查 │ │风格检查 │
│ SEC-001 │ │ARCH-001 │ │STYLE-001│
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└────────────┼────────────┘
│
▼
┌─────────────┐
│ 生成报告 │
│ 评分+建议 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 钉钉通知 │
│ Markdown │
└─────────────┘
2.2 事件流转
GitHub Push Event
│
▼
OpenClaw Gateway (/webhooks/github)
│
▼
验证 Webhook 签名 (hooks.token)
│
▼
调用 code-review-handler.js
│
├── 1. 获取变更文件列表 (GitHub API)
├── 2. 逐文件分析 (基于 ai-skills 规则库)
│ ├── 安全扫描 (硬编码/注入/XSS)
│ ├── 架构审查 (跨域引用/分层违规)
│ ├── TypeScript 检查 (any 类型/类型缺失)
│ ├── 代码风格 (导入顺序/命名/注释)
│ └── React 规范 (Hooks/组件/性能)
├── 3. 计算评分 (10 分制,加权算法)
└── 4. 生成 Markdown 报告
│
▼
钉钉 Markdown 消息推送
│
▼
开发者收到即时反馈
2.3 审查规则体系(基于 ai-skills 规范)
我们从 feature-mode-temp/ai-skills 梳理了完整的规范体系:
| 维度 | 规则数 | 严重等级 | 说明 |
|---|---|---|---|
| 安全 | 6 | 🔴 Blocking | 硬编码密码/API Key/Token、eval、innerHTML |
| 架构 | 3 | 🔴 Blocking | 跨域 feature 引用、pages 直接调用 request/fetch |
| TypeScript | 2 | 🔴/🟡 | 禁止 any、函数返回类型声明 |
| 代码风格 | 5 | 🟡 Suggestion | console.log、debugger、var、==、TODO |
| React | 3 | 🟡 Suggestion | Class Component、Table rowKey、useCallback |
| 命名规范 | 2 | 🟡 Suggestion | 事件处理 onXxx、异步函数 fetchXxx |
| 性能 | 2 | 🟡 Suggestion | 渲染中创建对象、链式 map |
三、核心实现
3.1 规则引擎设计
// REVIEW_RULES 结构
const REVIEW_RULES = [
{
id: 'SEC-001', // 规则标识
severity: 'blocking', // 严重等级
category: 'security', // 分类
pattern: /password\s*[=:]\s*["'][^"']+["']/i, // 正则匹配
message: '可能的硬编码密码', // 提示信息
suggestion: '使用环境变量管理敏感信息', // 修复建议
check: (match, filePath, code) => { // 自定义验证逻辑
// 返回 true 则触发规则
}
},
// ... 更多规则
];
3.2 智能评分算法
// 评分权重设计
let score = 10;
score -= totalIssues * 2.0; // Blocking 问题扣 2 分
score -= totalSuggestions * 0.5; // Suggestion 问题扣 0.5 分
score = Math.max(0, Math.min(10, score));
// 等级划分
// 🟢 8-10 分: 优秀,可直接合并
// 🟡 5-7 分: 良好,有小问题需改进
// 🔴 0-4 分: 较差,有严重问题必须修复
3.3 导入顺序检查(7 步法)
// ✅ 规范的导入顺序
import { FC, useState } from 'react'; // 1. React
import { Button, Table } from 'antd'; // 2. 第三方库
import UserTable from '@/components/UserTable'; // 3. 组件
import { fetchUserList } from '@/services/user';// 4. 其他(接口/常量/工具)
// import styles from './index.less'; // 5. 样式(优先 Tailwind)
interface UserListProps { /* 6. Props 类型 */ }
const UserList: FC<UserListProps> = () => { // 7. 组件实现
// ...
};
3.4 钉钉消息格式
## 📊 代码审查报告
**仓库**: owner/repo
**分支**: feature-branch
**作者**: developer
**提交**: Add new feature
### 总体评分: 🟡 7.5/10
📁 文件数: 3
➕ 新增: 120 行
➖ 删除: 45 行
🔴 严重问题: 1
🟡 建议: 3
### 🔴 严重问题 (必须修复)
**🔒 安全**
- **src/utils.ts:15** 使用了 `localStorage.setItem('token', ...)`,在发生 XSS 时 Token 可能被读取/窃取
💡 优先考虑使用 httpOnly Cookie(并配套 SameSite/CSRF 防护),或采用受控的安全存储方案与严格的 XSS 防护策略
### 🟡 建议改进
**🎨 代码风格**
- **src/utils.ts:15** 使用了 any 类型,建议指定具体类型
💡 使用 unknown 或显式类型替代 any
**⚛️ React**
- **src/index.ts:42** 遗留的 console.log
💡 生产代码中移除 console,或使用日志库
### ✅ 优点
- 关键问题集中在少数文件,定位与修复路径清晰
- 建议项均为可优化项,通常不影响功能正确性
---
*由 OpenClaw 代码审查助手生成*
*基于 ai-skills 规范 v1.0* 📋
3.5 工程落地关键点(避免“能讲但不好用”)
真实落地时,建议在“规则命中”之外补齐以下工程约束,才能让反馈稳定、可控、可扩展:
- 只审 Diff 与上下文策略:默认仅审 PR/Patch 的变更行;对需要上下文的规则(如跨域引用)再按需拉取同文件片段,避免全量扫描带来的噪音与成本。
-
脱敏与数据出域控制:在进入 AI 分析前做本地预检与脱敏(token/key/password、证书、URL 参数等),并支持规则白名单/抑制(例如
# review-ignore)以降低误报带来的摩擦。 - 幂等与去重:对同一 commit SHA 的审查结果做缓存与去重,避免 webhook 重放/重试导致重复刷屏。
- 限流与重试:对 GitHub API 429/5xx 做指数退避重试;对超大 diff/二进制文件做跳过与提示(例如“文件过大,建议拆分提交”)。
- 误报闭环:为每条规则提供“误报原因”与“怎么关闭/怎么改规则”的入口,持续迭代规则库而不是让团队学会忽略机器人。
四、Demo 演示
4.1 场景:开发者推送代码
开发者 完成一个功能,执行:
git add .
git commit -m "feat(user): add user list page with table and search"
git push origin feature/user-list
4.2 触发 Webhook
GitHub 发送 Push Event 到 OpenClaw:
{
"ref": "refs/heads/feature/user-list",
"repository": {
"full_name": "my-company/frontend-project"
},
"head_commit": {
"id": "abc123def456",
"message": "feat(user): add user list page with table and search",
"author": { "name": "张三" }
},
"pusher": { "name": "zhangsan" }
}
4.3 自动审查执行
OpenClaw Agent 接收到事件后:
- 获取变更文件:通过 GitHub API 获取 3 个变更文件
-
逐行分析:
-
src/pages/UserList/index.tsx:发现Table缺少rowKey(REACT-002) -
src/pages/UserList/index.tsx:发现直接调用request.get()(ARCH-002) -
src/features/user/components/UserTable/index.tsx:发现使用了any类型(TS-001) -
src/features/user/services/index.ts:发现console.log(STYLE-001)
-
-
计算评分:2 个 Blocking、2 个 Suggestion →
10 - 2*2 - 2*0.5= 5.0 分 🟡
4.4 钉钉通知
通常在较短时间内,开发者收到钉钉消息:
📊 代码审查: my-company/frontend-project (feature/user-list)
总体评分: 🟡 5.0/10
🔴 严重问题: 2
🟡 建议: 2
🔴 严重问题 (必须修复)
🏗️ 架构
- src/pages/UserList/index.tsx:42 页面中直接调用 request
💡 所有接口请求必须抽到 service 层
📝 TypeScript
- src/features/user/components/UserTable/index.tsx:15 使用了 any 类型
💡 使用 unknown 或显式类型替代 any
🟡 建议改进
⚛️ React
- src/pages/UserList/index.tsx:28 Table 组件可能缺少 rowKey
💡 为 Table 设置 rowKey 属性
🎨 代码风格
- src/features/user/services/index.ts:56 遗留的 console.log
💡 生产代码中移除 console,或使用日志库
4.5 开发者修复
开发者根据反馈修复:
// 修复前 ❌
const UserList = () => {
const [data, setData] = useState<any[]>([]); // any 类型
useEffect(() => {
request.get('/api/users').then(res => { // 直接调用 request
console.log(res); // console.log
setData(res.data);
});
}, []);
return <Table dataSource={data} />; // 缺少 rowKey
};
// 修复后 ✅
import { fetchUserList } from '@/features/user/services'; // service 层
interface User {
id: string;
name: string;
email: string;
}
const UserList = () => {
const [data, setData] = useState<User[]>([]); // 显式类型
useEffect(() => {
fetchUserList().then(setData); // 调用 service
}, []);
return <Table dataSource={data} rowKey="id" />; // 添加 rowKey
};
重新 push 后,评分提升至 9.5 分 🟢。
五、项目实战配置
5.1 目录结构
workspace/
├── CODE_REVIEW_GUIDELINE.md # 代码审查规范文档
├── scripts/
│ └── code-review-handler.js # 审查处理器
├── AGENTS.md # Agent 行为规范
├── SOUL.md # 角色设定与审查哲学
└── ...
5.2 环境变量配置
# GitHub Token(用于获取 diff)
export GITHUB_TOKEN="YOUR_GITHUB_TOKEN"
# 钉钉通知配置
export DINGTALK_CHANNEL="dingtalk-connector"
export DINGTALK_TARGET="" # 可选:指定接收人
5.3 GitHub Webhook 配置
- 进入 GitHub Repository → Settings → Webhooks
- 添加 Webhook:
-
Payload URL:
https://your-openclaw-domain/webhooks/github -
Content type:
application/json -
Secret: 与
hooks.token配置一致 - Events: 选择 "Just the push event" 或 "Pull requests"
-
Payload URL:
5.4 OpenClaw 配置
# config.yaml
hooks:
github:
enabled: true
path: /webhooks/github
token: your-webhook-secret
plugins:
dingtalk-connector:
enabled: true
webhook: https://oapi.dingtalk.com/robot/send?access_token=xxx
六、结语
本文围绕使用 OpenClaw 落地远程 Code Review 的实践展开。重点不在复杂技术细节,而在分享一种 Harness Engineering 的思路:将远程 Code Review 规范沉淀为可复用的标准化能力,减少项目间重复建设;同时把它作为一道质量防线,在变更更早阶段输出可操作的评审信号,提前预警潜在问题(例如不同大模型生成代码常见的质量参差不齐与风格漂移),让风险更早暴露、更易修复。
附录
- 框架: OpenClaw (AI Agent 框架)
- 运行时: Node.js 24+
- 规范来源: ai-skills
- 技术栈: React 18 + TypeScript + Umi Max + Ant Design v5 + Tailwind CSS
- 通知渠道: 钉钉 / 飞书 / Slack
"让规范成为基础设施,而不是依赖个人自觉。"
基于 OpenClaw 的自动化代码审查,让代码在进入主分支前获得一致的规范检查与风险提示,持续提升代码质量与协作效率。