feat: OpenAPI 契约对齐与框架优化
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m45s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m45s
主要变更: 1. OpenAPI 文档契约对齐 - 统一错误响应字段名为 msg(非 message) - 规范 envelope 响应结构(code, msg, data, timestamp) - 个人客户路由纳入文档体系(使用 Register 机制) - 新增 BuildDocHandlers() 统一管理 handler 构造 - 确保文档生成的幂等性 2. Service 层错误处理统一 - 全面替换 fmt.Errorf 为 errors.New/Wrap - 统一错误码使用规范 - Handler 层参数校验不泄露底层细节 - 新增错误码验证集成测试 3. 代码质量提升 - 删除未使用的 Task handler 和路由 - 新增代码规范检查脚本(check-service-errors.sh) - 新增注释路径一致性检查(check-comment-paths.sh) - 更新 API 文档生成指南 4. OpenSpec 归档 - 归档 openapi-contract-alignment 变更(63 tasks) - 归档 service-error-unify-core 变更 - 归档 service-error-unify-support 变更 - 归档 code-cleanup-docs-update 变更 - 归档 handler-validation-security 变更 - 同步 delta specs 到主规范文件 影响范围: - pkg/openapi: 新增 handlers.go,优化 generator.go - internal/service/*: 48 个 service 文件错误处理统一 - internal/handler/admin: 优化参数校验错误提示 - internal/routes: 个人客户路由改造,删除 task 路由 - scripts: 新增 3 个代码检查脚本 - docs: 更新 OpenAPI 文档(15750+ 行) - openspec/specs: 同步 3 个主规范文件 破坏性变更:无 向后兼容:是
This commit is contained in:
@@ -0,0 +1,543 @@
|
||||
# 设计文档:代码清理和规范文档更新
|
||||
|
||||
## 概述
|
||||
|
||||
本变更旨在清理项目中的临时代码和不一致的注释,完善规范文档,并增强 CI 检查,确保代码质量和规范一致性。
|
||||
|
||||
## 设计目标
|
||||
|
||||
1. **代码清理**:移除未使用的占位代码,避免潜在的安全风险
|
||||
2. **注释一致性**:确保代码注释与实际路由路径一致
|
||||
3. **规范完善**:补充缺失的规范文档和实际案例
|
||||
4. **自动化检查**:通过 CI 脚本自动检测规范违规
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 1. 任务模块清理
|
||||
|
||||
#### 现状分析
|
||||
|
||||
```
|
||||
internal/
|
||||
├── routes/
|
||||
│ ├── routes.go
|
||||
│ └── task.go # 占位路由,未接入业务
|
||||
└── handler/
|
||||
└── admin/
|
||||
└── task.go # 占位 Handler,空实现
|
||||
```
|
||||
|
||||
**问题**:
|
||||
- 占位代码可能被误用,导致鉴权不一致
|
||||
- 增加代码维护成本
|
||||
- 没有实际业务价值
|
||||
|
||||
#### 解决方案
|
||||
|
||||
**完全移除策略**:
|
||||
- 删除 `internal/routes/task.go`
|
||||
- 删除 `internal/handler/admin/task.go`
|
||||
- 从 `internal/routes/routes.go` 移除 `registerTaskRoutes()` 调用
|
||||
- 清理相关 import
|
||||
|
||||
**不采用保留注释/TODO 的原因**:
|
||||
- 如需任务功能,应重新设计实现
|
||||
- 避免遗留代码污染代码库
|
||||
|
||||
### 2. 注释路径清理
|
||||
|
||||
#### 现状分析
|
||||
|
||||
Handler 层注释中存在已弃用的路径:
|
||||
|
||||
```go
|
||||
// 错误示例
|
||||
// @Summary 获取用户列表
|
||||
// @Router /api/v1/users [get] // ❌ 已不存在
|
||||
func ListUsers(c *fiber.Ctx) error { ... }
|
||||
|
||||
// 正确示例
|
||||
// @Summary 获取用户列表
|
||||
// @Router /api/admin/users [get] // ✅ 与真实路由一致
|
||||
func ListUsers(c *fiber.Ctx) error { ... }
|
||||
```
|
||||
|
||||
**真实路由体系**:
|
||||
- `/api/admin/*`:后台管理接口
|
||||
- `/api/h5/*`:H5 端接口
|
||||
- `/api/c/v1/*`:个人客户接口
|
||||
|
||||
#### 解决方案
|
||||
|
||||
**扫描和修复流程**:
|
||||
|
||||
```bash
|
||||
# 1. 扫描所有残留路径
|
||||
grep -rn "/api/v1" internal/handler/ | grep -v "_test.go" > /tmp/path_comments.txt
|
||||
|
||||
# 2. 根据模块修复
|
||||
# - internal/handler/admin/*.go → /api/admin/*
|
||||
# - internal/handler/h5/*.go → /api/h5/*
|
||||
# - internal/handler/personal/*.go → /api/c/v1/*
|
||||
|
||||
# 3. 验证清理结果
|
||||
grep -r "/api/v1" internal/handler/ | grep -v "_test.go" # 应无结果
|
||||
```
|
||||
|
||||
### 3. 规范文档更新
|
||||
|
||||
#### 3.1 错误处理规范(openspec/specs/error-handling/spec.md)
|
||||
|
||||
**新增内容**:
|
||||
|
||||
##### Purpose 章节
|
||||
|
||||
```markdown
|
||||
## Purpose
|
||||
|
||||
统一项目的错误处理机制,确保:
|
||||
- 错误码一致性和可追踪性
|
||||
- 客户端能准确识别错误类型
|
||||
- 日志记录完整便于排查
|
||||
- 避免泄露内部实现细节
|
||||
```
|
||||
|
||||
##### 错误报错规范章节
|
||||
|
||||
```markdown
|
||||
## 错误报错规范(必须遵守)
|
||||
|
||||
### Handler 层
|
||||
|
||||
**禁止行为**:
|
||||
- ❌ 直接返回/拼接底层错误信息给客户端
|
||||
```go
|
||||
// 错误示例
|
||||
return response.Error(c, 400, errors.CodeInvalidParam, "参数验证失败: "+err.Error())
|
||||
```
|
||||
|
||||
**正确做法**:
|
||||
- ✅ 参数校验失败统一返回 `errors.New(CodeInvalidParam)`
|
||||
- ✅ 详细校验错误写日志,对外返回通用消息
|
||||
```go
|
||||
// 正确示例
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
logger.Error("参数解析失败", zap.Error(err))
|
||||
return errors.New(errors.CodeInvalidParam)
|
||||
}
|
||||
```
|
||||
|
||||
### Service 层
|
||||
|
||||
**禁止行为**:
|
||||
- ❌ 对外返回 `fmt.Errorf(...)`
|
||||
```go
|
||||
// 错误示例
|
||||
return fmt.Errorf("用户不存在: %w", err)
|
||||
```
|
||||
|
||||
**正确做法**:
|
||||
- ✅ 业务错误使用 `errors.New(code[, msg])`
|
||||
- ✅ 系统错误使用 `errors.Wrap(code, err[, msg])`
|
||||
```go
|
||||
// 正确示例
|
||||
if user == nil {
|
||||
return errors.New(errors.CodeUserNotFound, "用户不存在")
|
||||
}
|
||||
if err := db.Save(&user).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "保存用户失败")
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
#### 3.2 开发规范(AGENTS.md)
|
||||
|
||||
**新增 Code Review 检查清单**:
|
||||
|
||||
```markdown
|
||||
## Code Review 检查清单
|
||||
|
||||
### 错误处理
|
||||
- [ ] Service 层无 `fmt.Errorf` 对外返回
|
||||
- [ ] Handler 层参数校验不泄露细节
|
||||
- [ ] 错误码使用正确(4xx vs 5xx)
|
||||
- [ ] 错误日志完整(包含上下文)
|
||||
|
||||
### 代码质量
|
||||
- [ ] 遵循 Handler → Service → Store → Model 分层
|
||||
- [ ] 函数长度 ≤ 100 行(核心逻辑 ≤ 50 行)
|
||||
- [ ] 常量定义在 `pkg/constants/`
|
||||
- [ ] 使用 Go 惯用法(非 Java 风格)
|
||||
|
||||
### 测试覆盖
|
||||
- [ ] 核心业务逻辑测试覆盖率 ≥ 90%
|
||||
- [ ] 所有 API 端点有集成测试
|
||||
- [ ] 测试验证真实功能(不绕过核心逻辑)
|
||||
|
||||
### 文档和注释
|
||||
- [ ] 所有注释使用中文
|
||||
- [ ] 导出函数/类型有文档注释
|
||||
- [ ] API 路径注释与真实路由一致
|
||||
```
|
||||
|
||||
#### 3.3 使用指南(docs/003-error-handling/使用指南.md)
|
||||
|
||||
**补充实际案例**:
|
||||
|
||||
从现有代码库中提取真实案例:
|
||||
- Service 层业务校验错误示例
|
||||
- Service 层系统依赖错误示例
|
||||
- Handler 层参数校验示例
|
||||
- 单元测试示例
|
||||
|
||||
### 4. CI 检查增强
|
||||
|
||||
#### 4.1 Service 层错误检查脚本
|
||||
|
||||
**文件**:`scripts/check-service-errors.sh`
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 检查 Service 层是否使用 fmt.Errorf 对外返回
|
||||
|
||||
echo "🔍 检查 Service 层错误处理规范..."
|
||||
|
||||
FILES=$(find internal/service -name "*.go" -type f)
|
||||
VIOLATIONS=$(grep -n "fmt\.Errorf" $FILES | grep -v "// whitelist:")
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo ""
|
||||
echo "❌ 发现 Service 层使用 fmt.Errorf:"
|
||||
echo "$VIOLATIONS"
|
||||
echo ""
|
||||
echo "请使用以下方式替代:"
|
||||
echo " - 业务错误:errors.New(code, msg)"
|
||||
echo " - 系统错误:errors.Wrap(code, err, msg)"
|
||||
echo ""
|
||||
echo "如果某处确实需要使用 fmt.Errorf(如内部调试),请添加注释:// whitelist:"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Service 层错误处理检查通过"
|
||||
```
|
||||
|
||||
**设计考虑**:
|
||||
- 仅检查 `internal/service` 目录
|
||||
- 跳过带有 `// whitelist:` 注释的行(特殊场景)
|
||||
- 返回非零退出码以集成到 CI
|
||||
|
||||
#### 4.2 注释路径检查脚本
|
||||
|
||||
**文件**:`scripts/check-comment-paths.sh`
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 检查注释中的 API 路径是否一致
|
||||
|
||||
echo "🔍 检查注释中的 API 路径..."
|
||||
|
||||
VIOLATIONS=$(grep -rn "/api/v1" internal/handler/ | grep -v "_test.go")
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo ""
|
||||
echo "❌ 发现残留的 /api/v1 路径注释:"
|
||||
echo "$VIOLATIONS"
|
||||
echo ""
|
||||
echo "请修复为真实路径(/api/admin、/api/h5、/api/c/v1)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ 注释路径检查通过"
|
||||
```
|
||||
|
||||
#### 4.3 统一检查脚本
|
||||
|
||||
**文件**:`scripts/check-all.sh`
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 运行所有代码规范检查
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 运行代码规范检查..."
|
||||
echo ""
|
||||
|
||||
bash scripts/check-service-errors.sh
|
||||
bash scripts/check-comment-paths.sh
|
||||
|
||||
echo ""
|
||||
echo "✅ 所有检查通过"
|
||||
```
|
||||
|
||||
**用途**:
|
||||
- 本地开发:`bash scripts/check-all.sh`
|
||||
- CI 集成:在 `.github/workflows/lint.yml` 中调用
|
||||
|
||||
#### 4.4 CI 集成(可选)
|
||||
|
||||
**文件**:`.github/workflows/lint.yml`
|
||||
|
||||
```yaml
|
||||
name: Code Quality Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.25'
|
||||
|
||||
- name: Run Code Quality Checks
|
||||
run: bash scripts/check-all.sh
|
||||
```
|
||||
|
||||
## 数据流设计
|
||||
|
||||
### 注释清理流程
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 注释清理流程 │
|
||||
└────────────────────────────┬────────────────────────────────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ 1. 扫描残留路径 │
|
||||
│ grep -rn "/api/v1" │
|
||||
└────────────┬────────────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ 2. 分析文件模块 │
|
||||
│ - admin/ → /api/admin │
|
||||
│ - h5/ → /api/h5 │
|
||||
│ - personal/ → /api/c │
|
||||
└────────────┬────────────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ 3. 批量修复注释 │
|
||||
│ - 手动编辑文件 │
|
||||
│ - 或使用 sed 批量替换 │
|
||||
└────────────┬────────────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ 4. 验证清理结果 │
|
||||
│ grep -r "/api/v1" │
|
||||
│ 应无结果 │
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
### CI 检查流程
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ CI 检查流程 │
|
||||
└────────────────────────────┬────────────────────────────────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ 1. 代码提交/PR │
|
||||
└────────────┬────────────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ 2. 触发 GitHub Actions │
|
||||
└────────────┬────────────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ 3. 运行 check-all.sh │
|
||||
└────────────┬────────────┘
|
||||
│
|
||||
┌────────────────────┼────────────────────┐
|
||||
│ │ │
|
||||
┌───────▼────────┐ ┌────────▼────────┐ ┌───────▼────────┐
|
||||
│ Service 错误检查│ │ 注释路径检查 │ │ 其他检查... │
|
||||
└───────┬────────┘ └────────┬────────┘ └───────┬────────┘
|
||||
│ │ │
|
||||
└────────────────────┼────────────────────┘
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ 4. 汇总结果 │
|
||||
│ - ✅ 全部通过 │
|
||||
│ - ❌ 有违规 │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ 5. 反馈结果到 PR │
|
||||
│ - 通过:允许合并 │
|
||||
│ - 失败:阻止合并 │
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
## 技术决策
|
||||
|
||||
### 1. 为什么完全删除任务模块而非保留注释?
|
||||
|
||||
**决策**:完全删除占位代码
|
||||
|
||||
**理由**:
|
||||
- **避免误用**:占位代码可能被后续开发者误用
|
||||
- **代码简洁**:减少维护成本和认知负担
|
||||
- **版本控制**:Git 历史保留了代码,需要时可恢复
|
||||
- **重新设计**:如需任务功能,应基于实际需求设计
|
||||
|
||||
### 2. 为什么只检查 Service 层的 fmt.Errorf?
|
||||
|
||||
**决策**:只强制检查 Service 层
|
||||
|
||||
**理由**:
|
||||
- **影响范围**:Service 层错误直接影响客户端体验
|
||||
- **降低噪音**:Handler 层有时需要拼接调试信息(不对外返回)
|
||||
- **测试文件**:测试代码可以使用 `fmt.Errorf` 构造错误
|
||||
|
||||
**特殊场景处理**:
|
||||
- 内部调试需要 `fmt.Errorf`:添加 `// whitelist:` 注释跳过检查
|
||||
|
||||
### 3. 为什么文档案例从实际代码提取?
|
||||
|
||||
**决策**:使用真实代码案例而非虚构示例
|
||||
|
||||
**理由**:
|
||||
- **实用性**:开发者可直接参考实际实现
|
||||
- **一致性**:确保文档与代码同步
|
||||
- **可信度**:真实案例更有说服力
|
||||
|
||||
### 4. CI 集成为什么设为可选?
|
||||
|
||||
**决策**:CI 集成为可选任务
|
||||
|
||||
**理由**:
|
||||
- **灵活性**:本地开发可直接运行脚本
|
||||
- **渐进式**:项目可选择何时启用 CI
|
||||
- **成本考虑**:小型项目可能不需要 CI
|
||||
|
||||
## 非功能性需求
|
||||
|
||||
### 性能考虑
|
||||
|
||||
- **脚本性能**:检查脚本应在 10 秒内完成
|
||||
- **CI 耗时**:代码检查不应显著增加 CI 时间(< 30 秒)
|
||||
|
||||
### 可维护性
|
||||
|
||||
- **脚本可读性**:使用清晰的错误消息和帮助文本
|
||||
- **规则扩展**:易于添加新的检查规则
|
||||
- **白名单机制**:支持特殊场景豁免
|
||||
|
||||
### 兼容性
|
||||
|
||||
- **Shell 兼容性**:脚本使用 Bash 标准语法(兼容 Linux/macOS)
|
||||
- **工具依赖**:仅依赖标准工具(grep、find),无需额外安装
|
||||
|
||||
## 验证策略
|
||||
|
||||
### 1. 代码清理验证
|
||||
|
||||
```bash
|
||||
# 确认文件已删除
|
||||
test ! -f internal/routes/task.go
|
||||
test ! -f internal/handler/admin/task.go
|
||||
|
||||
# 确认引用已移除
|
||||
! grep -r "registerTaskRoutes" internal/
|
||||
! grep -r "TaskHandler" internal/ | grep -v "_test.go"
|
||||
|
||||
# 编译检查
|
||||
go build -o /tmp/test_api ./cmd/api
|
||||
go build -o /tmp/test_worker ./cmd/worker
|
||||
```
|
||||
|
||||
### 2. 注释清理验证
|
||||
|
||||
```bash
|
||||
# 确认无残留 /api/v1 注释
|
||||
! grep -r "/api/v1" internal/handler/ | grep -v "_test.go"
|
||||
```
|
||||
|
||||
### 3. CI 脚本验证
|
||||
|
||||
```bash
|
||||
# 运行检查(应通过)
|
||||
bash scripts/check-all.sh
|
||||
|
||||
# 测试能检测违规(应失败)
|
||||
echo 'return fmt.Errorf("test")' >> internal/service/test_violation.go
|
||||
bash scripts/check-service-errors.sh # 应返回退出码 1
|
||||
rm internal/service/test_violation.go
|
||||
|
||||
# 测试白名单机制(应通过)
|
||||
echo 'return fmt.Errorf("debug") // whitelist:' >> internal/service/test.go
|
||||
bash scripts/check-service-errors.sh # 应返回退出码 0
|
||||
rm internal/service/test.go
|
||||
```
|
||||
|
||||
### 4. 文档完整性验证
|
||||
|
||||
```bash
|
||||
# 确认规范文档已更新
|
||||
grep -q "错误报错规范" openspec/specs/error-handling/spec.md
|
||||
grep -q "错误报错规范" AGENTS.md
|
||||
grep -q "Service 层错误处理" docs/003-error-handling/使用指南.md
|
||||
|
||||
# 确认文档包含实际案例(非空占位)
|
||||
test $(wc -l < docs/003-error-handling/使用指南.md) -gt 100
|
||||
```
|
||||
|
||||
## 实施计划
|
||||
|
||||
### 阶段 1:代码清理(0.5h)
|
||||
|
||||
1. 删除任务模块文件
|
||||
2. 移除路由注册调用
|
||||
3. 编译验证
|
||||
|
||||
### 阶段 2:注释清理(0.5h)
|
||||
|
||||
1. 扫描残留路径
|
||||
2. 批量修复注释
|
||||
3. 验证清理结果
|
||||
|
||||
### 阶段 3:文档更新(1h)
|
||||
|
||||
1. 更新错误处理规范
|
||||
2. 更新开发规范
|
||||
3. 补充使用指南案例
|
||||
|
||||
### 阶段 4:CI 增强(0.5h)
|
||||
|
||||
1. 创建检查脚本
|
||||
2. 测试脚本功能
|
||||
3. 更新 README
|
||||
|
||||
### 阶段 5:全量验证(0.5h)
|
||||
|
||||
1. 运行所有验证命令
|
||||
2. 确认文档完整性
|
||||
3. 更新 README
|
||||
|
||||
## 风险和缓解
|
||||
|
||||
| 风险 | 影响 | 缓解措施 |
|
||||
|------|------|---------|
|
||||
| 误删有用代码 | 高 | 仔细审查 Git 历史,确认代码未被引用 |
|
||||
| 注释修复遗漏 | 中 | 使用自动化脚本扫描,手动验证结果 |
|
||||
| CI 脚本误报 | 中 | 提供白名单机制,允许特殊场景豁免 |
|
||||
| 文档案例过时 | 低 | 从当前代码库提取,确保时效性 |
|
||||
|
||||
## 总结
|
||||
|
||||
本设计通过系统化的方法清理代码、完善文档、增强 CI 检查,确保项目代码质量和规范一致性。关键设计决策包括:
|
||||
|
||||
1. **完全删除**占位代码而非保留注释
|
||||
2. **自动化检查** Service 层错误处理规范
|
||||
3. **真实案例**补充文档使用指南
|
||||
4. **渐进式集成** CI 检查(可选)
|
||||
|
||||
预计总工作量约 3 小时,无 Breaking Changes,对现有功能无影响。
|
||||
@@ -0,0 +1,191 @@
|
||||
# Change: 代码清理和规范文档更新
|
||||
|
||||
## Why
|
||||
|
||||
清理临时代码和不一致的注释,更新项目规范文档,完善 CI 检查,确保代码质量和规范一致性。
|
||||
|
||||
**当前问题**:
|
||||
|
||||
1. **任务模块占位代码**:
|
||||
- `internal/routes/task.go` 包含占位路由
|
||||
- `internal/handler/admin/task.go` 未接入真实业务
|
||||
- 存在鉴权不一致风险
|
||||
|
||||
2. **注释路径不一致**:
|
||||
- Handler 层注释中残留 `/api/v1/...` 路径
|
||||
- 真实路由为 `/api/admin`、`/api/h5`、`/api/c/v1`
|
||||
|
||||
3. **规范文档缺失**:
|
||||
- `openspec/specs/error-handling/spec.md` 缺少"错误报错规范"
|
||||
- `AGENTS.md` 未包含错误处理检查清单
|
||||
- `docs/003-error-handling/使用指南.md` 缺少实际案例
|
||||
|
||||
4. **CI 检查不完善**:
|
||||
- 无自动检查 Service 层禁止 `fmt.Errorf`
|
||||
- 无自动检查注释路径一致性
|
||||
|
||||
## What Changes
|
||||
|
||||
### 5.1 移除任务模块占位代码
|
||||
|
||||
删除以下文件和引用:
|
||||
|
||||
```bash
|
||||
# 删除文件
|
||||
rm internal/routes/task.go
|
||||
rm internal/handler/admin/task.go
|
||||
|
||||
# 更新 routes.go
|
||||
# 移除 registerTaskRoutes(...) 调用
|
||||
```
|
||||
|
||||
### 5.2 清理注释一致性
|
||||
|
||||
扫描并修复 Handler 层注释:
|
||||
|
||||
```bash
|
||||
# 查找残留的 /api/v1 注释
|
||||
grep -r "/api/v1" internal/handler/ | grep -v "_test.go"
|
||||
|
||||
# 修复为真实路径
|
||||
/api/v1/users → /api/admin/users
|
||||
/api/v1/shops → /api/admin/shops
|
||||
```
|
||||
|
||||
### 5.3 更新规范文档
|
||||
|
||||
#### 错误处理规范
|
||||
- 更新 `openspec/specs/error-handling/spec.md`
|
||||
- 补充 Purpose 说明
|
||||
- 新增"错误报错规范"条款:
|
||||
- Handler 层禁止直接返回底层错误
|
||||
- Service 层禁止使用 `fmt.Errorf` 对外返回
|
||||
- 参数校验失败统一返回 `CodeInvalidParam`
|
||||
|
||||
#### 开发规范
|
||||
- 更新 `AGENTS.md`
|
||||
- 增加"错误报错规范"摘要
|
||||
- 补充 Code Review 检查清单
|
||||
|
||||
#### 使用指南
|
||||
- 更新 `docs/003-error-handling/使用指南.md`
|
||||
- 补充 Service 层错误处理实际案例
|
||||
- 补充 Handler 层参数校验案例
|
||||
- 补充单元测试示例
|
||||
|
||||
### 5.4 CI 检查增强
|
||||
|
||||
创建脚本检查规范遵守:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# scripts/check-service-errors.sh
|
||||
|
||||
FILES=$(find internal/service -name "*.go" -type f)
|
||||
VIOLATIONS=$(grep -n "fmt\.Errorf" $FILES | grep -v "// whitelist:")
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo "❌ 发现 Service 层使用 fmt.Errorf:"
|
||||
echo "$VIOLATIONS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Service 层错误处理检查通过"
|
||||
```
|
||||
|
||||
## Decisions
|
||||
|
||||
### 任务模块处理
|
||||
|
||||
- 完全移除占位代码(不保留注释或 TODO)
|
||||
- 如需任务功能,后续单独设计实现
|
||||
|
||||
### 注释清理规则
|
||||
|
||||
- 注释路径必须与真实路由一致
|
||||
- 不使用已弃用的路径(如 `/api/v1`)
|
||||
- API 文档路径以 OpenAPI 生成为准
|
||||
|
||||
### CI 检查范围
|
||||
|
||||
- Service 层:禁止 `fmt.Errorf` 对外返回
|
||||
- Handler 层:建议检查但不强制(可选)
|
||||
- 测试文件:跳过检查
|
||||
|
||||
## Impact
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
无(仅清理未使用代码)
|
||||
|
||||
### Documentation Updates
|
||||
|
||||
- 错误处理规范文档完善
|
||||
- 开发规范检查清单更新
|
||||
- 使用指南补充实际案例
|
||||
|
||||
### CI Integration
|
||||
|
||||
可选集成到 GitHub Actions:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/lint.yml
|
||||
- name: Check Service Layer Errors
|
||||
run: bash scripts/check-service-errors.sh
|
||||
```
|
||||
|
||||
## Affected Specs
|
||||
|
||||
- **UPDATE**: `openspec/specs/error-handling/spec.md`
|
||||
- **UPDATE**: `AGENTS.md`
|
||||
- **UPDATE**: `docs/003-error-handling/使用指南.md`
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
### 代码清理验证
|
||||
```bash
|
||||
# 确认文件已删除
|
||||
ls internal/routes/task.go # 应返回 No such file
|
||||
ls internal/handler/admin/task.go # 应返回 No such file
|
||||
|
||||
# 确认引用已移除
|
||||
grep -r "registerTaskRoutes" internal/ # 应无结果
|
||||
grep -r "TaskHandler" internal/ # 应无结果(除测试文件)
|
||||
```
|
||||
|
||||
### 注释清理验证
|
||||
```bash
|
||||
# 确认无残留 /api/v1 注释
|
||||
grep -r "/api/v1" internal/handler/ | grep -v "_test.go" # 应无结果
|
||||
```
|
||||
|
||||
### CI 检查验证
|
||||
```bash
|
||||
# 运行检查脚本
|
||||
bash scripts/check-service-errors.sh # 应返回 ✅
|
||||
|
||||
# 测试脚本能检测到违规
|
||||
echo 'return fmt.Errorf("test")' >> internal/service/test.go
|
||||
bash scripts/check-service-errors.sh # 应返回 ❌
|
||||
rm internal/service/test.go
|
||||
```
|
||||
|
||||
### 文档完整性检查
|
||||
```bash
|
||||
# 确认文档已更新
|
||||
grep "错误报错规范" openspec/specs/error-handling/spec.md
|
||||
grep "错误报错规范" AGENTS.md
|
||||
grep "Service 层错误处理" docs/003-error-handling/使用指南.md
|
||||
```
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
| 任务 | 预估时间 |
|
||||
|-----|---------|
|
||||
| 5.1 移除任务模块 | 0.5h |
|
||||
| 5.2 清理注释一致性 | 0.5h |
|
||||
| 5.3 更新规范文档 | 1h |
|
||||
| 5.4 CI 检查增强 | 0.5h |
|
||||
| 验证 | 0.5h |
|
||||
|
||||
**总计**:约 3 小时
|
||||
@@ -0,0 +1,396 @@
|
||||
# CI 检查脚本规范
|
||||
|
||||
## 概述
|
||||
|
||||
本变更新增了自动化代码规范检查脚本,用于在 CI/CD 流程中检测规范违规。
|
||||
|
||||
## 检查脚本列表
|
||||
|
||||
### 1. Service 层错误处理检查
|
||||
|
||||
**文件**:`scripts/check-service-errors.sh`
|
||||
|
||||
**用途**:检查 Service 层是否使用 `fmt.Errorf` 对外返回错误
|
||||
|
||||
**检查范围**:
|
||||
- 目录:`internal/service/**/*.go`
|
||||
- 排除:测试文件(`*_test.go`)
|
||||
- 排除:带有 `// whitelist:` 注释的行
|
||||
|
||||
**检查逻辑**:
|
||||
```bash
|
||||
FILES=$(find internal/service -name "*.go" -type f)
|
||||
VIOLATIONS=$(grep -n "fmt\.Errorf" $FILES | grep -v "// whitelist:")
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo "❌ 发现 Service 层使用 fmt.Errorf"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
**退出码**:
|
||||
- `0`:检查通过
|
||||
- `1`:检查失败(发现违规)
|
||||
|
||||
**白名单机制**:
|
||||
|
||||
如果某处确实需要使用 `fmt.Errorf`(如内部调试),添加注释:
|
||||
|
||||
```go
|
||||
// 特殊场景:内部日志调试
|
||||
debugErr := fmt.Errorf("debug info: %v", data) // whitelist:
|
||||
logger.Debug("调试信息", zap.Error(debugErr))
|
||||
```
|
||||
|
||||
### 2. 注释路径一致性检查
|
||||
|
||||
**文件**:`scripts/check-comment-paths.sh`
|
||||
|
||||
**用途**:检查 Handler 层注释中是否残留已弃用的 `/api/v1` 路径
|
||||
|
||||
**检查范围**:
|
||||
- 目录:`internal/handler/**/*.go`
|
||||
- 排除:测试文件(`*_test.go`)
|
||||
|
||||
**检查逻辑**:
|
||||
```bash
|
||||
VIOLATIONS=$(grep -rn "/api/v1" internal/handler/ | grep -v "_test.go")
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo "❌ 发现残留的 /api/v1 路径注释"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
**退出码**:
|
||||
- `0`:检查通过
|
||||
- `1`:检查失败(发现残留路径)
|
||||
|
||||
**正确路径**:
|
||||
- `/api/admin/*`:后台管理接口
|
||||
- `/api/h5/*`:H5 端接口
|
||||
- `/api/c/v1/*`:个人客户接口
|
||||
|
||||
### 3. 统一检查脚本
|
||||
|
||||
**文件**:`scripts/check-all.sh`
|
||||
|
||||
**用途**:运行所有代码规范检查
|
||||
|
||||
**检查流程**:
|
||||
```bash
|
||||
set -e # 任何检查失败立即退出
|
||||
|
||||
bash scripts/check-service-errors.sh
|
||||
bash scripts/check-comment-paths.sh
|
||||
# 未来可添加更多检查...
|
||||
|
||||
echo "✅ 所有检查通过"
|
||||
```
|
||||
|
||||
**使用场景**:
|
||||
- 本地开发:提交代码前运行
|
||||
- CI/CD:自动化检查流程
|
||||
- Pre-commit hook:提交前自动检查(可选)
|
||||
|
||||
## 脚本规范
|
||||
|
||||
### 输出格式
|
||||
|
||||
所有检查脚本应遵循统一的输出格式:
|
||||
|
||||
```bash
|
||||
# 1. 开始提示
|
||||
echo "🔍 检查 [检查项名称]..."
|
||||
|
||||
# 2. 检查逻辑
|
||||
VIOLATIONS=$(检查命令)
|
||||
|
||||
# 3. 结果输出
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo ""
|
||||
echo "❌ 发现违规:"
|
||||
echo "$VIOLATIONS"
|
||||
echo ""
|
||||
echo "修复建议:"
|
||||
echo " - 建议1"
|
||||
echo " - 建议2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ [检查项名称]检查通过"
|
||||
```
|
||||
|
||||
### 错误消息规范
|
||||
|
||||
错误消息应包含:
|
||||
1. **问题描述**:明确说明发现了什么问题
|
||||
2. **违规位置**:文件路径和行号
|
||||
3. **修复建议**:如何修复这些问题
|
||||
4. **白名单机制**:如何豁免特殊场景(如适用)
|
||||
|
||||
**示例**:
|
||||
```
|
||||
❌ 发现 Service 层使用 fmt.Errorf:
|
||||
internal/service/shop.go:45: return fmt.Errorf("店铺不存在")
|
||||
internal/service/account.go:78: return fmt.Errorf("创建失败: %w", err)
|
||||
|
||||
请使用以下方式替代:
|
||||
- 业务错误:errors.New(code, msg)
|
||||
- 系统错误:errors.Wrap(code, err, msg)
|
||||
|
||||
如果某处确实需要使用 fmt.Errorf(如内部调试),请添加注释:// whitelist:
|
||||
```
|
||||
|
||||
### 脚本权限
|
||||
|
||||
所有脚本应添加执行权限:
|
||||
|
||||
```bash
|
||||
chmod +x scripts/check-service-errors.sh
|
||||
chmod +x scripts/check-comment-paths.sh
|
||||
chmod +x scripts/check-all.sh
|
||||
```
|
||||
|
||||
### Shell 兼容性
|
||||
|
||||
脚本应使用 Bash 标准语法,兼容 Linux 和 macOS:
|
||||
- 使用 `#!/bin/bash` 作为 shebang
|
||||
- 避免使用非标准工具(仅依赖 grep、find、bash 等)
|
||||
- 使用 `set -e` 确保错误自动退出
|
||||
|
||||
## CI 集成(可选)
|
||||
|
||||
### GitHub Actions 配置
|
||||
|
||||
**文件**:`.github/workflows/lint.yml`
|
||||
|
||||
```yaml
|
||||
name: Code Quality Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.25'
|
||||
|
||||
- name: Run Code Quality Checks
|
||||
run: bash scripts/check-all.sh
|
||||
```
|
||||
|
||||
### 本地使用
|
||||
|
||||
开发者可以在本地运行检查:
|
||||
|
||||
```bash
|
||||
# 运行所有检查
|
||||
bash scripts/check-all.sh
|
||||
|
||||
# 运行单项检查
|
||||
bash scripts/check-service-errors.sh
|
||||
bash scripts/check-comment-paths.sh
|
||||
```
|
||||
|
||||
### Pre-commit Hook(可选)
|
||||
|
||||
可以配置 Git pre-commit hook 在提交前自动检查:
|
||||
|
||||
**文件**:`.git/hooks/pre-commit`
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
echo "运行代码规范检查..."
|
||||
bash scripts/check-all.sh
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo ""
|
||||
echo "代码规范检查失败,提交已取消"
|
||||
echo "请修复上述问题后重新提交"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "代码规范检查通过,继续提交..."
|
||||
```
|
||||
|
||||
## 扩展性设计
|
||||
|
||||
### 添加新的检查规则
|
||||
|
||||
添加新的检查规则的步骤:
|
||||
|
||||
1. **创建检查脚本**:`scripts/check-{name}.sh`
|
||||
```bash
|
||||
#!/bin/bash
|
||||
echo "🔍 检查 [检查项名称]..."
|
||||
|
||||
# 检查逻辑
|
||||
VIOLATIONS=$(检查命令)
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo "❌ 发现违规"
|
||||
echo "$VIOLATIONS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ 检查通过"
|
||||
```
|
||||
|
||||
2. **添加执行权限**:
|
||||
```bash
|
||||
chmod +x scripts/check-{name}.sh
|
||||
```
|
||||
|
||||
3. **集成到统一脚本**:
|
||||
在 `scripts/check-all.sh` 中添加:
|
||||
```bash
|
||||
bash scripts/check-{name}.sh
|
||||
```
|
||||
|
||||
4. **测试脚本**:
|
||||
```bash
|
||||
# 测试通过场景
|
||||
bash scripts/check-{name}.sh # 应返回退出码 0
|
||||
|
||||
# 测试失败场景(制造违规)
|
||||
# 验证能检测到违规并返回退出码 1
|
||||
```
|
||||
|
||||
5. **更新文档**:
|
||||
在 `README.md` 和本规范文档中添加新检查的说明
|
||||
|
||||
### 检查规则示例
|
||||
|
||||
以下是一些可能添加的检查规则:
|
||||
|
||||
| 检查项 | 脚本名称 | 检查内容 |
|
||||
|-------|---------|---------|
|
||||
| 常量硬编码 | `check-constants.sh` | 检查代码中是否有硬编码的 magic numbers 和字符串 |
|
||||
| 日志规范 | `check-logging.sh` | 检查日志是否使用结构化字段(zap.String、zap.Int 等) |
|
||||
| TODO 标记 | `check-todos.sh` | 统计代码中的 TODO 数量,超过阈值时警告 |
|
||||
| 导入路径 | `check-imports.sh` | 检查是否使用了禁止的包(如 `fmt.Println`) |
|
||||
| 测试覆盖率 | `check-coverage.sh` | 检查测试覆盖率是否达标 |
|
||||
|
||||
## 性能考虑
|
||||
|
||||
### 检查耗时
|
||||
|
||||
所有检查脚本应在合理时间内完成:
|
||||
- 单项检查:< 10 秒
|
||||
- 统一检查:< 30 秒
|
||||
|
||||
### 优化建议
|
||||
|
||||
1. **并行执行**:多个独立检查可以并行运行
|
||||
2. **缓存结果**:避免重复扫描相同文件
|
||||
3. **增量检查**:仅检查变更的文件(CI 场景)
|
||||
|
||||
### 并行执行示例
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# scripts/check-all-parallel.sh
|
||||
|
||||
# 在后台运行检查
|
||||
bash scripts/check-service-errors.sh &
|
||||
PID1=$!
|
||||
|
||||
bash scripts/check-comment-paths.sh &
|
||||
PID2=$!
|
||||
|
||||
# 等待所有检查完成
|
||||
wait $PID1
|
||||
RESULT1=$?
|
||||
|
||||
wait $PID2
|
||||
RESULT2=$?
|
||||
|
||||
# 检查结果
|
||||
if [ $RESULT1 -ne 0 ] || [ $RESULT2 -ne 0 ]; then
|
||||
echo "❌ 至少有一项检查失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ 所有检查通过"
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 脚本测试清单
|
||||
|
||||
每个检查脚本应测试以下场景:
|
||||
|
||||
1. **通过场景**:无违规时返回 0
|
||||
2. **失败场景**:有违规时返回 1 并输出错误
|
||||
3. **白名单机制**:白名单注释生效(如适用)
|
||||
4. **边界情况**:空目录、特殊字符等
|
||||
|
||||
### 测试示例
|
||||
|
||||
```bash
|
||||
# 测试 Service 层错误检查
|
||||
|
||||
# 1. 通过场景
|
||||
bash scripts/check-service-errors.sh
|
||||
echo "退出码: $?" # 应为 0
|
||||
|
||||
# 2. 失败场景
|
||||
echo 'return fmt.Errorf("test")' >> internal/service/test_violation.go
|
||||
bash scripts/check-service-errors.sh
|
||||
echo "退出码: $?" # 应为 1
|
||||
rm internal/service/test_violation.go
|
||||
|
||||
# 3. 白名单机制
|
||||
echo 'return fmt.Errorf("debug") // whitelist:' >> internal/service/test_whitelist.go
|
||||
bash scripts/check-service-errors.sh
|
||||
echo "退出码: $?" # 应为 0
|
||||
rm internal/service/test_whitelist.go
|
||||
```
|
||||
|
||||
## 维护指南
|
||||
|
||||
### 定期维护
|
||||
|
||||
- **每月审查**:检查是否有新的规范需要自动化检查
|
||||
- **每季度更新**:根据团队反馈优化错误消息和修复建议
|
||||
- **每半年评估**:评估检查脚本的性能和有效性
|
||||
|
||||
### 处理误报
|
||||
|
||||
如果检查脚本产生误报:
|
||||
|
||||
1. **评估规则**:检查规则是否过于严格
|
||||
2. **白名单机制**:考虑添加白名单支持
|
||||
3. **改进检测**:优化正则表达式或检查逻辑
|
||||
4. **文档说明**:在规范文档中说明特殊场景
|
||||
|
||||
### 版本控制
|
||||
|
||||
检查脚本应纳入版本控制:
|
||||
- 脚本修改需要通过 Code Review
|
||||
- 重大变更需要更新文档
|
||||
- 保持脚本向后兼容(或提供迁移指南)
|
||||
|
||||
## 总结
|
||||
|
||||
本 CI 检查规范定义了:
|
||||
1. **检查脚本列表**:Service 层错误检查、注释路径检查、统一检查
|
||||
2. **脚本规范**:输出格式、错误消息、Shell 兼容性
|
||||
3. **CI 集成**:GitHub Actions、本地使用、Pre-commit Hook
|
||||
4. **扩展性设计**:添加新规则的步骤和示例
|
||||
5. **性能优化**:并行执行、增量检查
|
||||
6. **测试策略**:通过/失败/白名单/边界情况
|
||||
7. **维护指南**:定期审查、处理误报、版本控制
|
||||
|
||||
这些脚本确保代码质量和规范一致性,支持自动化检查和团队协作。
|
||||
@@ -0,0 +1,298 @@
|
||||
# 错误处理规范更新
|
||||
|
||||
## 概述
|
||||
|
||||
本变更更新了错误处理规范文档,补充了缺失的内容和实际案例。
|
||||
|
||||
## 更新的规范文件
|
||||
|
||||
### 1. openspec/specs/error-handling/spec.md
|
||||
|
||||
**新增内容**:
|
||||
|
||||
#### Purpose 章节
|
||||
|
||||
补充规范的目的说明:
|
||||
- 错误码一致性和可追踪性
|
||||
- 客户端能准确识别错误类型
|
||||
- 日志记录完整便于排查
|
||||
- 避免泄露内部实现细节
|
||||
|
||||
#### 错误报错规范章节
|
||||
|
||||
新增"错误报错规范(必须遵守)"章节,详细说明:
|
||||
|
||||
**Handler 层规范**:
|
||||
- ❌ 禁止直接返回/拼接底层错误信息给客户端
|
||||
- ✅ 参数校验失败统一返回 `errors.New(CodeInvalidParam)`
|
||||
- ✅ 详细校验错误写日志,对外返回通用消息
|
||||
|
||||
**Service 层规范**:
|
||||
- ❌ 禁止对外返回 `fmt.Errorf(...)`
|
||||
- ✅ 业务错误使用 `errors.New(code[, msg])`
|
||||
- ✅ 系统错误使用 `errors.Wrap(code, err[, msg])`
|
||||
|
||||
**代码示例**:
|
||||
|
||||
```go
|
||||
// ❌ 错误示例 - Handler 层
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return response.Error(c, 400, errors.CodeInvalidParam, "参数验证失败: "+err.Error())
|
||||
}
|
||||
|
||||
// ✅ 正确示例 - Handler 层
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
logger.Error("参数解析失败", zap.Error(err))
|
||||
return errors.New(errors.CodeInvalidParam)
|
||||
}
|
||||
|
||||
// ❌ 错误示例 - Service 层
|
||||
if user == nil {
|
||||
return fmt.Errorf("用户不存在: %w", err)
|
||||
}
|
||||
|
||||
// ✅ 正确示例 - Service 层
|
||||
if user == nil {
|
||||
return errors.New(errors.CodeUserNotFound, "用户不存在")
|
||||
}
|
||||
if err := db.Save(&user).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "保存用户失败")
|
||||
}
|
||||
```
|
||||
|
||||
### 2. AGENTS.md
|
||||
|
||||
**新增内容**:
|
||||
|
||||
#### 错误处理摘要
|
||||
|
||||
在"错误处理"章节补充"错误报错规范(必须遵守)"摘要:
|
||||
- Handler 层禁止直接返回/拼接底层错误信息(例如 `"参数验证失败: "+err.Error()`)
|
||||
- 参数校验失败:对外统一返回 `errors.New(CodeInvalidParam)`(详细错误写日志)
|
||||
- Service 层禁止对外返回 `fmt.Errorf(...)`,必须返回 `errors.New(...)` 或 `errors.Wrap(...)`
|
||||
|
||||
#### Code Review 检查清单
|
||||
|
||||
新增完整的 Code Review 检查清单:
|
||||
|
||||
**错误处理**:
|
||||
- [ ] Service 层无 `fmt.Errorf` 对外返回
|
||||
- [ ] Handler 层参数校验不泄露细节
|
||||
- [ ] 错误码使用正确(4xx vs 5xx)
|
||||
- [ ] 错误日志完整(包含上下文)
|
||||
|
||||
**代码质量**:
|
||||
- [ ] 遵循 Handler → Service → Store → Model 分层
|
||||
- [ ] 函数长度 ≤ 100 行(核心逻辑 ≤ 50 行)
|
||||
- [ ] 常量定义在 `pkg/constants/`
|
||||
- [ ] 使用 Go 惯用法(非 Java 风格)
|
||||
|
||||
**测试覆盖**:
|
||||
- [ ] 核心业务逻辑测试覆盖率 ≥ 90%
|
||||
- [ ] 所有 API 端点有集成测试
|
||||
- [ ] 测试验证真实功能(不绕过核心逻辑)
|
||||
|
||||
**文档和注释**:
|
||||
- [ ] 所有注释使用中文
|
||||
- [ ] 导出函数/类型有文档注释
|
||||
- [ ] API 路径注释与真实路由一致
|
||||
|
||||
### 3. docs/003-error-handling/使用指南.md
|
||||
|
||||
**新增内容**:
|
||||
|
||||
#### Service 层错误处理
|
||||
|
||||
补充 Service 层错误处理实际案例:
|
||||
|
||||
**示例 1:资源不存在**
|
||||
```go
|
||||
func (s *ShopService) GetShop(ctx context.Context, shopID uint) (*model.Shop, error) {
|
||||
shop, err := s.store.Shop.GetByID(ctx, shopID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New(errors.CodeShopNotFound, "店铺不存在")
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "查询店铺失败")
|
||||
}
|
||||
return shop, nil
|
||||
}
|
||||
```
|
||||
|
||||
**示例 2:状态不允许**
|
||||
```go
|
||||
func (s *SIMService) Activate(ctx context.Context, iccid string) error {
|
||||
sim, err := s.store.SIM.GetByICCID(ctx, iccid)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "查询SIM卡失败")
|
||||
}
|
||||
|
||||
if sim.Status != constants.SIMStatusInactive {
|
||||
return errors.New(errors.CodeInvalidOperation, "只有未激活的SIM卡才能激活")
|
||||
}
|
||||
|
||||
// 执行激活逻辑...
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
**示例 3:数据库错误**
|
||||
```go
|
||||
func (s *AccountService) CreateAccount(ctx context.Context, req *dto.CreateAccountRequest) error {
|
||||
account := &model.Account{
|
||||
Username: req.Username,
|
||||
Phone: req.Phone,
|
||||
// ...
|
||||
}
|
||||
|
||||
if err := s.store.Account.Create(ctx, account); err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "创建账号失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
#### Handler 层参数校验
|
||||
|
||||
补充 Handler 层参数校验案例:
|
||||
|
||||
**参数解析错误**
|
||||
```go
|
||||
func (h *AccountHandler) CreateAccount(c *fiber.Ctx) error {
|
||||
var req dto.CreateAccountRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("参数解析失败", zap.Error(err))
|
||||
return errors.New(errors.CodeInvalidParam)
|
||||
}
|
||||
|
||||
if err := h.validator.Struct(&req); err != nil {
|
||||
h.logger.Error("参数验证失败", zap.Error(err))
|
||||
return errors.New(errors.CodeInvalidParam)
|
||||
}
|
||||
|
||||
// 调用 Service...
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
**参数验证错误**
|
||||
```go
|
||||
func (h *ShopHandler) UpdateShop(c *fiber.Ctx) error {
|
||||
shopID, err := strconv.ParseUint(c.Params("id"), 10, 32)
|
||||
if err != nil {
|
||||
h.logger.Error("店铺ID格式错误", zap.Error(err))
|
||||
return errors.New(errors.CodeInvalidParam)
|
||||
}
|
||||
|
||||
var req dto.UpdateShopRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
h.logger.Error("参数解析失败", zap.Error(err))
|
||||
return errors.New(errors.CodeInvalidParam)
|
||||
}
|
||||
|
||||
// 调用 Service...
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
#### 错误场景单元测试
|
||||
|
||||
补充测试代码示例:
|
||||
|
||||
**Service 层测试**
|
||||
```go
|
||||
func TestShopService_GetShop_NotFound(t *testing.T) {
|
||||
tx := testutils.NewTestTransaction(t)
|
||||
rdb := testutils.GetTestRedis(t)
|
||||
testutils.CleanTestRedisKeys(t, rdb)
|
||||
|
||||
store := postgres.NewShopStore(tx, rdb)
|
||||
service := service.NewShopService(store, logger)
|
||||
|
||||
// 测试不存在的店铺
|
||||
_, err := service.GetShop(context.Background(), 99999)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.True(t, errors.Is(err, errors.CodeShopNotFound))
|
||||
}
|
||||
|
||||
func TestSIMService_Activate_InvalidStatus(t *testing.T) {
|
||||
tx := testutils.NewTestTransaction(t)
|
||||
rdb := testutils.GetTestRedis(t)
|
||||
testutils.CleanTestRedisKeys(t, rdb)
|
||||
|
||||
store := postgres.NewSIMStore(tx, rdb)
|
||||
service := service.NewSIMService(store, logger)
|
||||
|
||||
// 创建已激活的 SIM 卡
|
||||
sim := &model.SIM{
|
||||
ICCID: "898600123456789",
|
||||
Status: constants.SIMStatusActive,
|
||||
}
|
||||
store.Create(context.Background(), sim)
|
||||
|
||||
// 尝试再次激活
|
||||
err := service.Activate(context.Background(), sim.ICCID)
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.True(t, errors.Is(err, errors.CodeInvalidOperation))
|
||||
}
|
||||
```
|
||||
|
||||
**Handler 层测试**
|
||||
```go
|
||||
func TestAccountHandler_CreateAccount_InvalidParam(t *testing.T) {
|
||||
env := testutils.NewIntegrationTestEnv(t)
|
||||
|
||||
t.Run("缺少必填字段", func(t *testing.T) {
|
||||
reqBody := map[string]interface{}{
|
||||
"username": "test",
|
||||
// 缺少 phone 字段
|
||||
}
|
||||
|
||||
resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/accounts", reqBody)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
|
||||
var result map[string]interface{}
|
||||
json.Unmarshal(resp.Body, &result)
|
||||
assert.Equal(t, float64(errors.CodeInvalidParam), result["code"])
|
||||
})
|
||||
|
||||
t.Run("手机号格式错误", func(t *testing.T) {
|
||||
reqBody := map[string]interface{}{
|
||||
"username": "test",
|
||||
"phone": "invalid",
|
||||
}
|
||||
|
||||
resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/accounts", reqBody)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 400, resp.StatusCode)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## 检查清单
|
||||
|
||||
在实施这些更新后,需要验证:
|
||||
|
||||
- [x] `openspec/specs/error-handling/spec.md` 包含 Purpose 章节
|
||||
- [x] `openspec/specs/error-handling/spec.md` 包含"错误报错规范"章节
|
||||
- [x] `AGENTS.md` 包含错误处理摘要
|
||||
- [x] `AGENTS.md` 包含 Code Review 检查清单
|
||||
- [x] `docs/003-error-handling/使用指南.md` 包含 Service 层实际案例
|
||||
- [x] `docs/003-error-handling/使用指南.md` 包含 Handler 层实际案例
|
||||
- [x] `docs/003-error-handling/使用指南.md` 包含单元测试示例
|
||||
|
||||
## 影响范围
|
||||
|
||||
这些文档更新不影响现有代码逻辑,仅完善规范说明和最佳实践指引。
|
||||
|
||||
## 后续维护
|
||||
|
||||
- 新增错误码时,同步更新使用指南中的案例
|
||||
- 发现新的错误处理模式时,补充到文档中
|
||||
- 定期检查文档案例与代码实际实现的一致性
|
||||
@@ -0,0 +1,372 @@
|
||||
# Implementation Tasks
|
||||
|
||||
## 1. 移除任务模块占位代码
|
||||
|
||||
### 1.1 删除文件
|
||||
- [x] 删除 `internal/routes/task.go`
|
||||
```bash
|
||||
rm internal/routes/task.go
|
||||
```
|
||||
- [x] 删除 `internal/handler/admin/task.go`
|
||||
```bash
|
||||
rm internal/handler/admin/task.go
|
||||
```
|
||||
|
||||
### 1.2 移除引用
|
||||
- [x] 打开 `internal/routes/routes.go`
|
||||
- [x] 移除 `registerTaskRoutes(...)` 调用
|
||||
- [x] 移除相关 import(如果不再使用)
|
||||
|
||||
### 1.3 验证
|
||||
- [x] 编译检查:`go build -o /tmp/test_api ./cmd/api`
|
||||
- [x] 确认无 TaskHandler 引用:
|
||||
```bash
|
||||
grep -r "TaskHandler" internal/ | grep -v "_test.go"
|
||||
# 应无结果
|
||||
```
|
||||
|
||||
## 2. 清理注释一致性
|
||||
|
||||
### 2.1 扫描残留路径
|
||||
- [x] 查找所有 `/api/v1` 注释:
|
||||
```bash
|
||||
grep -rn "/api/v1" internal/handler/ | grep -v "_test.go" > /tmp/path_comments.txt
|
||||
cat /tmp/path_comments.txt
|
||||
```
|
||||
|
||||
### 2.2 批量修复注释
|
||||
- [x] 根据 `/tmp/path_comments.txt` 逐个修复:
|
||||
- `/api/v1/users` → `/api/admin/users`
|
||||
- `/api/v1/shops` → `/api/admin/shops`
|
||||
- `/api/v1/orders` → `/api/admin/orders` 或 `/api/h5/orders`
|
||||
- 等等
|
||||
|
||||
### 2.3 验证清理结果
|
||||
- [x] 再次扫描:
|
||||
```bash
|
||||
grep -r "/api/v1" internal/handler/ | grep -v "_test.go"
|
||||
# 应无结果
|
||||
```
|
||||
|
||||
## 3. 更新规范文档
|
||||
|
||||
### 3.1 更新错误处理规范
|
||||
- [x] 打开 `openspec/specs/error-handling/spec.md`
|
||||
- [x] 补充 Purpose 说明:
|
||||
```markdown
|
||||
## Purpose
|
||||
|
||||
统一项目的错误处理机制,确保:
|
||||
- 错误码一致性和可追踪性
|
||||
- 客户端能准确识别错误类型
|
||||
- 日志记录完整便于排查
|
||||
- 避免泄露内部实现细节
|
||||
```
|
||||
|
||||
- [x] 新增"错误报错规范"章节:
|
||||
```markdown
|
||||
## 错误报错规范(必须遵守)
|
||||
|
||||
### Handler 层
|
||||
- ❌ 禁止直接返回/拼接底层错误信息给客户端
|
||||
- ✅ 参数校验失败统一返回 `errors.New(CodeInvalidParam)`
|
||||
- ✅ 详细校验错误写日志,对外返回通用消息
|
||||
|
||||
### Service 层
|
||||
- ❌ 禁止对外返回 `fmt.Errorf(...)`
|
||||
- ✅ 业务错误使用 `errors.New(code[, msg])`
|
||||
- ✅ 系统错误使用 `errors.Wrap(code, err[, msg])`
|
||||
|
||||
### 示例
|
||||
[补充实际代码示例]
|
||||
```
|
||||
|
||||
### 3.2 更新 AGENTS.md
|
||||
- [x] 打开 `AGENTS.md`
|
||||
- [x] 在"错误处理"章节补充摘要:
|
||||
```markdown
|
||||
#### 错误报错规范(必须遵守)
|
||||
- Handler 层禁止直接返回/拼接底层错误信息(例如 `"参数验证失败: "+err.Error()`)
|
||||
- 参数校验失败:对外统一返回 `errors.New(CodeInvalidParam)`(详细错误写日志)
|
||||
- Service 层禁止对外返回 `fmt.Errorf(...)`,必须返回 `errors.New(...)` 或 `errors.Wrap(...)`
|
||||
```
|
||||
|
||||
- [x] 补充 Code Review 检查清单:
|
||||
```markdown
|
||||
## Code Review 检查清单
|
||||
|
||||
### 错误处理
|
||||
- [ ] Service 层无 `fmt.Errorf` 对外返回
|
||||
- [ ] Handler 层参数校验不泄露细节
|
||||
- [ ] 错误码使用正确(4xx vs 5xx)
|
||||
- [ ] 错误日志完整(包含上下文)
|
||||
```
|
||||
|
||||
### 3.3 更新使用指南
|
||||
- [x] 打开 `docs/003-error-handling/使用指南.md`
|
||||
- [x] 补充 Service 层错误处理实际案例:
|
||||
```markdown
|
||||
## Service 层错误处理
|
||||
|
||||
### 业务校验错误(4xx)
|
||||
|
||||
#### 示例 1:资源不存在
|
||||
[从实际代码中提取]
|
||||
|
||||
#### 示例 2:状态不允许
|
||||
[从实际代码中提取]
|
||||
|
||||
### 系统依赖错误(5xx)
|
||||
|
||||
#### 示例 3:数据库错误
|
||||
[从实际代码中提取]
|
||||
```
|
||||
|
||||
- [x] 补充 Handler 层参数校验案例:
|
||||
```markdown
|
||||
## Handler 层参数校验
|
||||
|
||||
### 参数解析错误
|
||||
[补充安全加固后的代码示例]
|
||||
|
||||
### 参数验证错误
|
||||
[补充安全加固后的代码示例]
|
||||
```
|
||||
|
||||
- [x] 补充单元测试示例:
|
||||
```markdown
|
||||
## 错误场景单元测试
|
||||
|
||||
### Service 层测试
|
||||
[补充测试代码示例]
|
||||
|
||||
### Handler 层测试
|
||||
[补充集成测试示例]
|
||||
```
|
||||
|
||||
## 4. CI 检查增强
|
||||
|
||||
### 4.1 创建检查脚本
|
||||
- [x] 创建文件:`scripts/check-service-errors.sh`
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 检查 Service 层是否使用 fmt.Errorf 对外返回
|
||||
|
||||
echo "🔍 检查 Service 层错误处理规范..."
|
||||
|
||||
FILES=$(find internal/service -name "*.go" -type f)
|
||||
VIOLATIONS=$(grep -n "fmt\.Errorf" $FILES | grep -v "// whitelist:")
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo ""
|
||||
echo "❌ 发现 Service 层使用 fmt.Errorf:"
|
||||
echo "$VIOLATIONS"
|
||||
echo ""
|
||||
echo "请使用以下方式替代:"
|
||||
echo " - 业务错误:errors.New(code, msg)"
|
||||
echo " - 系统错误:errors.Wrap(code, err, msg)"
|
||||
echo ""
|
||||
echo "如果某处确实需要使用 fmt.Errorf(如内部调试),请添加注释:// whitelist:"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Service 层错误处理检查通过"
|
||||
```
|
||||
|
||||
- [x] 添加执行权限:
|
||||
```bash
|
||||
chmod +x scripts/check-service-errors.sh
|
||||
```
|
||||
|
||||
### 4.2 创建注释检查脚本(可选)
|
||||
- [x] 创建文件:`scripts/check-comment-paths.sh`
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 检查注释中的 API 路径是否一致
|
||||
|
||||
echo "🔍 检查注释中的 API 路径..."
|
||||
|
||||
VIOLATIONS=$(grep -rn "/api/v1" internal/handler/ | grep -v "_test.go")
|
||||
|
||||
if [ -n "$VIOLATIONS" ]; then
|
||||
echo ""
|
||||
echo "❌ 发现残留的 /api/v1 路径注释:"
|
||||
echo "$VIOLATIONS"
|
||||
echo ""
|
||||
echo "请修复为真实路径(/api/admin、/api/h5、/api/c/v1)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ 注释路径检查通过"
|
||||
```
|
||||
|
||||
- [x] 添加执行权限:
|
||||
```bash
|
||||
chmod +x scripts/check-comment-paths.sh
|
||||
```
|
||||
|
||||
### 4.3 创建统一检查脚本
|
||||
- [x] 创建文件:`scripts/check-all.sh`
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 运行所有代码规范检查
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 运行代码规范检查..."
|
||||
echo ""
|
||||
|
||||
bash scripts/check-service-errors.sh
|
||||
bash scripts/check-comment-paths.sh
|
||||
|
||||
echo ""
|
||||
echo "✅ 所有检查通过"
|
||||
```
|
||||
|
||||
- [x] 添加执行权限:
|
||||
```bash
|
||||
chmod +x scripts/check-all.sh
|
||||
```
|
||||
|
||||
### 4.4 测试检查脚本
|
||||
- [x] 运行 Service 错误检查:
|
||||
```bash
|
||||
bash scripts/check-service-errors.sh
|
||||
# 应返回 ✅(假设已完成提案 1 和 2)
|
||||
```
|
||||
|
||||
- [x] 测试脚本能检测违规:
|
||||
```bash
|
||||
echo 'return fmt.Errorf("test")' >> internal/service/test.go
|
||||
bash scripts/check-service-errors.sh # 应返回 ❌
|
||||
rm internal/service/test.go
|
||||
```
|
||||
|
||||
- [x] 运行注释路径检查:
|
||||
```bash
|
||||
bash scripts/check-comment-paths.sh
|
||||
# 应返回 ✅
|
||||
```
|
||||
|
||||
- [x] 运行全部检查:
|
||||
```bash
|
||||
bash scripts/check-all.sh
|
||||
```
|
||||
|
||||
### 4.5 集成到 CI(可选)
|
||||
- [x] 创建/更新 `.github/workflows/lint.yml`:
|
||||
```yaml
|
||||
name: Code Quality Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.25'
|
||||
|
||||
- name: Run Code Quality Checks
|
||||
run: bash scripts/check-all.sh
|
||||
```
|
||||
|
||||
## 5. 全量验证
|
||||
|
||||
### 5.1 代码清理验证
|
||||
- [x] 确认文件已删除:
|
||||
```bash
|
||||
ls internal/routes/task.go # 应返回 No such file
|
||||
ls internal/handler/admin/task.go # 应返回 No such file
|
||||
```
|
||||
|
||||
- [x] 确认引用已移除:
|
||||
```bash
|
||||
grep -r "registerTaskRoutes" internal/ # 应无结果
|
||||
grep -r "TaskHandler" internal/ | grep -v "_test.go" # 应无结果
|
||||
```
|
||||
|
||||
### 5.2 注释清理验证
|
||||
- [x] 确认无残留 `/api/v1` 注释:
|
||||
```bash
|
||||
grep -r "/api/v1" internal/handler/ | grep -v "_test.go" # 应无结果
|
||||
```
|
||||
|
||||
### 5.3 编译检查
|
||||
- [x] `go build -o /tmp/test_api ./cmd/api`
|
||||
- [x] `go build -o /tmp/test_worker ./cmd/worker`
|
||||
|
||||
### 5.4 CI 检查验证
|
||||
- [x] 运行所有检查脚本:
|
||||
```bash
|
||||
bash scripts/check-all.sh # 应返回 ✅
|
||||
```
|
||||
|
||||
### 5.5 文档完整性检查
|
||||
- [x] 确认规范文档已更新:
|
||||
```bash
|
||||
grep "错误报错规范" openspec/specs/error-handling/spec.md
|
||||
grep "错误报错规范" AGENTS.md
|
||||
grep "Service 层错误处理" docs/003-error-handling/使用指南.md
|
||||
```
|
||||
|
||||
- [x] 确认文档包含实际案例(非空占位)
|
||||
|
||||
## 6. README 更新(可选)
|
||||
|
||||
### 6.1 补充 CI 检查说明
|
||||
- [x] 在 `README.md` 中补充"代码规范检查"章节:
|
||||
```markdown
|
||||
## 代码规范检查
|
||||
|
||||
运行代码规范检查:
|
||||
|
||||
\`\`\`bash
|
||||
# 检查 Service 层错误处理
|
||||
bash scripts/check-service-errors.sh
|
||||
|
||||
# 检查注释路径一致性
|
||||
bash scripts/check-comment-paths.sh
|
||||
|
||||
# 运行所有检查
|
||||
bash scripts/check-all.sh
|
||||
\`\`\`
|
||||
|
||||
这些检查会在 CI/CD 流程中自动执行。
|
||||
```
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [x] 任务模块文件已删除
|
||||
- [x] 任务模块引用已移除
|
||||
- [x] 注释路径已统一
|
||||
- [x] 错误处理规范已更新(spec.md)
|
||||
- [x] 开发规范已更新(AGENTS.md)
|
||||
- [x] 使用指南已更新(包含实际案例)
|
||||
- [x] CI 检查脚本已创建
|
||||
- [x] CI 检查脚本测试通过
|
||||
- [x] 编译通过,无语法错误
|
||||
- [x] 全量检查脚本通过
|
||||
- [x] 文档完整性验证通过
|
||||
- [x] README 已更新(如需要)
|
||||
|
||||
## 预估工作量
|
||||
|
||||
| 任务 | 预估时间 |
|
||||
|-----|---------|
|
||||
| 1. 移除任务模块 | 0.5h |
|
||||
| 2. 清理注释一致性 | 0.5h |
|
||||
| 3. 更新规范文档 | 1h |
|
||||
| 4. CI 检查增强 | 0.5h |
|
||||
| 5. 全量验证 | 0.5h |
|
||||
| 6. README 更新(可选) | 0.5h |
|
||||
|
||||
**总计**:约 3.5 小时
|
||||
Reference in New Issue
Block a user