Files
lijiaoqiao/scripts/auto_review/auto_review.sh

487 lines
16 KiB
Bash
Executable File
Raw Permalink 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.
#!/bin/bash
#===============================================================================
# 自动化周期性Review脚本
# 功能每3小时执行一次项目全面review生成报告并分发任务
# 使用:./auto_review.sh [hourly|daily|force]
#===============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
REVIEW_DIR="$PROJECT_ROOT/review"
REPORT_DIR="$REVIEW_DIR/daily_reports"
KNOWLEDGE_DIR="$REVIEW_DIR/knowledge_base"
TASK_QUEUE="$REVIEW_DIR/task_queue.json"
LOG_DIR="$PROJECT_ROOT/logs/auto_review"
# 加载配置
source "$SCRIPT_DIR/auto_review_config.sh"
#-------------------------------------------------------------------------------
# 日志函数
#-------------------------------------------------------------------------------
log() {
local level=$1
shift
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*"
echo "$msg"
echo "$msg" >> "$LOG_DIR/review_$(date '+%Y%m%d').log"
}
#-------------------------------------------------------------------------------
# 初始化
#-------------------------------------------------------------------------------
init() {
mkdir -p "$LOG_DIR" "$REPORT_DIR" "$KNOWLEDGE_DIR"
# 初始化任务队列
if [ ! -f "$TASK_QUEUE" ]; then
echo '{"tasks":[], "last_updated":"", "last_review_date":""}' > "$TASK_QUEUE"
fi
log "INFO" "Auto review system initialized"
}
#-------------------------------------------------------------------------------
# 获取文档变更状态
#-------------------------------------------------------------------------------
get_doc_changes() {
local since="${1:-24h}"
git -C "$PROJECT_ROOT" diff --name-only --since="$since" -- "docs/" "review/" 2>/dev/null || echo ""
}
#-------------------------------------------------------------------------------
# 读取上一份报告
#-------------------------------------------------------------------------------
read_last_report() {
local last_report=$(ls -t "$REPORT_DIR"/daily_review_*.md 2>/dev/null | head -1)
if [ -n "$last_report" ]; then
echo "$last_report"
else
echo ""
fi
}
#-------------------------------------------------------------------------------
# 提取未完成任务
#-------------------------------------------------------------------------------
extract_pending_tasks() {
local report_file="$1"
if [ -z "$report_file" ] || [ ! -f "$report_file" ]; then
echo "[]"
return
fi
# 提取P0/P1任务
grep -E "^\s*\|.*P[01].*\|" "$report_file" 2>/dev/null | \
grep -v "完成\|已关闭\|CLOSED" | \
sed -E 's/\|/,/g' | \
awk -F',' '{print "{\"id\":\""$1"\",\"desc\":\""$3"\",\"owner\":\""$4"\"}"}' | \
jq -s '.' 2>/dev/null || echo "[]"
}
#-------------------------------------------------------------------------------
# 执行Review检查
#-------------------------------------------------------------------------------
perform_review() {
local review_type="$1"
log "INFO" "Starting $review_type review..."
# 收集变更文件
local changes=""
local change_count=0
changes=$(get_doc_changes "3 hours ago" 2>/dev/null || echo "")
change_count=$(echo "$changes" | grep -c "." 2>/dev/null || echo "0")
# 检查是否有新的设计文档
local new_docs=0
new_docs=$(git -C "$PROJECT_ROOT" status --porcelain "docs/" 2>/dev/null | grep "^??" | wc -l 2>/dev/null || echo "0")
new_docs=${new_docs:-0}
# 检查未完成任务
local last_report=$(read_last_report)
local pending_tasks="[]"
local pending_count=0
if [ -n "$last_report" ] && [ -f "$last_report" ]; then
pending_tasks=$(extract_pending_tasks "$last_report" 2>/dev/null || echo "[]")
pending_count=$(echo "$pending_tasks" | jq 'length' 2>/dev/null || echo "0")
fi
pending_count=${pending_count:-0}
# 执行快速检查模拟专家review
local issues_found=0
# 检查关键文档是否存在
local critical_doc
for critical_doc in "$REVIEW_DIR/comprehensive_expert_review_report_v2_2026-03-18.md" "$PROJECT_ROOT/docs/architecture_solution_v1_2026-03-18.md"; do
if [ ! -f "$critical_doc" ]; then
log "WARN" "Critical document missing: $critical_doc"
issues_found=$((issues_found + 1))
fi
done
# 构建JSON确保所有值都是有效的
local change_files_json="[]"
if [ -n "$changes" ]; then
change_files_json=$(echo "$changes" | jq -R -s 'split("\n") | map(select(length > 0))' 2>/dev/null || echo "[]")
fi
# 确定是否需要处理
local action_required="false"
if [ "$issues_found" -gt 0 ] || [ "$change_count" -gt 0 ]; then
action_required="true"
fi
# 返回Review结果
cat << EOF
{
"review_type": "$review_type",
"timestamp": "$(date -Iseconds)",
"changes_count": $change_count,
"new_docs_count": $new_docs,
"pending_tasks_count": $pending_count,
"issues_found": $issues_found,
"change_files": $change_files_json,
"action_required": $action_required
}
EOF
}
#-------------------------------------------------------------------------------
# 生成每日报告
#-------------------------------------------------------------------------------
generate_daily_report() {
local review_data="$1"
local date_str=$(date '+%Y-%m-%d')
log "INFO" "Generating daily review report for $date_str..."
local report_file="$REPORT_DIR/daily_review_${date_str}.md"
local last_report=$(read_last_report)
# 提取review数据
local changes_count new_docs_count pending_tasks_count issues_found
changes_count=$(echo "$review_data" | jq -r '.changes_count // 0' 2>/dev/null || echo "0")
new_docs_count=$(echo "$review_data" | jq -r '.new_docs_count // 0' 2>/dev/null || echo "0")
pending_tasks_count=$(echo "$review_data" | jq -r '.pending_tasks_count // 0' 2>/dev/null || echo "0")
issues_found=$(echo "$review_data" | jq -r '.issues_found // 0' 2>/dev/null || echo "0")
# 提取变更文件列表
local change_list
change_list=$(echo "$review_data" | jq -r '.change_files[] // empty' 2>/dev/null | sed 's/^/- /' || echo "无变更")
# 生成报告头部
cat > "$report_file" << EOF
# 立交桥项目每日Review报告
> 生成时间:$(date '+%Y-%m-%d %H:%M:%S')
> 报告日期:$date_str
> Review类型每日全面检查
---
## 一、Review执行摘要
| 指标 | 数值 | 较昨日 |
|------|------|--------|
| 文档变更数 | $changes_count | - |
| 新增文档数 | $new_docs_count | - |
| 待完成任务 | $pending_tasks_count | - |
| 发现问题 | $issues_found | - |
---
## 二、变更文件清单
$change_list
---
## 三、待完成任务追踪
### 3.1 P0问题阻断上线
EOF
# 添加P0任务列表
if [ -n "$last_report" ]; then
grep -A 50 "### 3.1 P0问题" "$last_report" 2>/dev/null | head -30 >> "$report_file" || echo "| - | - | - | - |" >> "$report_file"
else
echo "| 编号 | 问题描述 | Owner | 状态 |" >> "$report_file"
echo "|-----|----------|-------|------|" >> "$report_file"
echo "| - | 暂无 | - | - |" >> "$report_file"
fi
cat >> "$report_file" << EOF
### 3.2 P1问题高优先级
EOF
if [ -n "$last_report" ]; then
grep -A 30 "### 3.2 P1问题" "$last_report" 2>/dev/null | head -20 >> "$report_file" || echo "| - | - | - |" >> "$report_file"
else
echo "| 编号 | 问题描述 | Owner |" >> "$report_file"
echo "|-----|----------|-------|" >> "$report_file"
fi
# 确定行动项文本
local action_text="无"
local new_issue_text="| - | - | 无新问题 | - |"
if [ "$issues_found" -gt 0 ]; then
action_text="存在 $issues_found 个问题需处理"
new_issue_text="| NEW-001 | P1 | 新发现的问题(待详细记录) | $(date '+%Y-%m-%d %H:%M') |"
fi
cat >> "$report_file" << EOF
---
## 四、新发现问题
| 编号 | 等级 | 问题描述 | 发现时间 |
|------|------|----------|----------|
$new_issue_text
---
## 五、建议行动项
1. **立即处理**$action_text
2. **持续跟进**$pending_tasks_count 个待办任务
3. **文档更新**$new_docs_count 个新文档待审核
---
## 六、专家评审状态
| 轮次 | 主题 | 结论 | 日期 |
|------|------|------|------|
| Round-1 | 架构与替换路径 | CONDITIONAL GO | 2026-03-19 |
| Round-2 | 兼容与计费一致性 | CONDITIONAL GO | 2026-03-22 |
| Round-3 | 安全与合规攻防 | CONDITIONAL GO | 2026-03-25 |
| Round-4 | 可靠性与回滚演练 | CONDITIONAL GO | 2026-03-29 |
---
**报告状态**:自动生成
**下次更新**$(date -d '+3 hours' '+%Y-%m-%d %H:%M')
EOF
log "INFO" "Daily report generated: $report_file"
echo "$report_file"
}
#-------------------------------------------------------------------------------
# 更新任务队列
#-------------------------------------------------------------------------------
update_task_queue() {
local review_data="$1"
local date_str=$(date '+%Y-%m-%d')
# 提取数据
local changes_count issues_found action_required
changes_count=$(echo "$review_data" | jq -r '.changes_count // 0' 2>/dev/null || echo "0")
issues_found=$(echo "$review_data" | jq -r '.issues_found // 0' 2>/dev/null || echo "0")
action_required=$(echo "$review_data" | jq -r '.action_required // "false"' 2>/dev/null || echo "false")
# 读取当前队列
local current_queue=$(cat "$TASK_QUEUE" 2>/dev/null || echo '{"tasks":[]}')
# 更新JSON
local updated
updated=$(echo "$current_queue" | jq --arg timestamp "$(date -Iseconds)" \
--arg date "$date_str" \
--argjson changes "$changes_count" \
--argjson issues "$issues_found" \
'.last_updated = $timestamp | .last_review_date = $date | .review_stats.total_reviews += 1 | .review_stats.issues_found += $issues')
echo "$updated" > "$TASK_QUEUE"
# 如果有问题需要处理,生成任务文件
if [ "$issues_found" -gt 0 ]; then
local task_file="$REVIEW_DIR/pending_tasks_$(date '+%Y%m%d_%H%M%S').json"
echo "$review_data" > "$task_file"
log "WARN" "Issues found! Task file created: $task_file"
fi
}
#-------------------------------------------------------------------------------
# 生成Claude Code任务
#-------------------------------------------------------------------------------
generate_claude_tasks() {
local review_data="$1"
local date_str=$(date '+%Y-%m-%d')
# 提取数据
local needs_action issues_found changes_count pending_tasks_count
needs_action=$(echo "$review_data" | jq -r '.action_required // "false"' 2>/dev/null || echo "false")
issues_found=$(echo "$review_data" | jq -r '.issues_found // 0' 2>/dev/null || echo "0")
changes_count=$(echo "$review_data" | jq -r '.changes_count // 0' 2>/dev/null || echo "0")
pending_tasks_count=$(echo "$review_data" | jq -r '.pending_tasks_count // 0' 2>/dev/null || echo "0")
# 提取变更文件列表
local change_list
change_list=$(echo "$review_data" | jq -r '.change_files[] // empty' 2>/dev/null | sed 's/^/1. 审核文档:/' || echo "1. 检查并处理review发现的问题")
if [ "$needs_action" = "true" ]; then
local task_file="$REVIEW_DIR/claude_tasks_${date_str}.md"
cat > "$task_file" << EOF
# Claude Code 执行任务
> 生成时间:$(date '+%Y-%m-%d %H:%M:%S')
> 触发条件Review发现需要处理的问题
## 执行要求
请Claude Code CLI按照以下规范执行
1. **遵循superpowers插件规范**
2. **严格按照项目规划设计执行**
3. **优先处理P0问题**
## 待处理问题清单
- 问题数量:$issues_found
- 文档变更:$changes_count 个文件
- 待办任务:$pending_tasks_count 个
## 具体任务
$change_list
---
**状态**:等待执行
**优先级**:高
EOF
log "INFO" "Claude tasks generated: $task_file"
echo "$task_file"
else
echo ""
fi
}
#-------------------------------------------------------------------------------
# 更新经验知识库每日3点执行
#-------------------------------------------------------------------------------
update_knowledge_base() {
local is_daily=$(date '+%H')
# 只在每天3点执行
if [ "$is_daily" != "03" ]; then
log "INFO" "Skipping knowledge base update (not 3am, current: ${is_daily}00)"
return 0
fi
log "INFO" "Updating knowledge base..."
local date_str=$(date '+%Y-%m-%d')
local kb_file="$KNOWLEDGE_BASE/rules_and_experience_${date_str}.md"
# 收集当天经验
local issues=""
local last_report=$(read_last_report)
if [ -n "$last_report" ]; then
issues=$(grep -E "^\|.*P[01]" "$last_report" 2>/dev/null | wc -l)
fi
cat > "$kb_file" << EOF
# 立交桥项目经验与规则
> 更新时间:$(date '+%Y-%m-%d %H:%M:%S')
> 版本:$(date '+%Y%m%d')
## 一、项目关键规范
### 1.1 架构原则
- Provider Adapter抽象层设计
- 三层降级策略(同平台换号/同区域换平台/全局降级)
- 分阶段验证S2-A/B/C1/C2
### 1.2 安全红线
- 内网隔离 + mTLS双向认证
- 契约漂移CI阻断
- 密钥90天轮换
### 1.3 质量门禁
- 接管率 >= 99.9% 覆盖率
- 自动回滚 <= 10分钟
- 服务恢复 <= 30分钟
- 用户通知 <= 15分钟
## 二、待解决P0问题
- 数量:$issues 个(来自最新报告)
## 三、专家评审结论
| 维度 | 结论 | 评分 |
|------|------|------|
| 架构 | CONDITIONAL GO | 3.5/5 |
| API设计 | CONDITIONAL GO | 4.0/5 |
| 安全防护 | CONDITIONAL GO | 3.0/5 |
| 业务合规 | CONDITIONAL GO | 3.5/5 |
| 计费精度 | CONDITIONAL GO | 4.0/5 |
| 可靠性 | CONDITIONAL GO | 3.0/5 |
## 四、行动优先级
1. **P0**:安全验证、契约测试、降级演练
2. **P1**用户体验、SLA文档、计费准确性
3. **P2**SDK开发、法务确认、DDoS防护
---
**状态**:每日自动更新
**下次更新**$(date -d '+1 day' -d '3:00' '+%Y-%m-%d %H:%M')
EOF
log "INFO" "Knowledge base updated: $kb_file"
}
#-------------------------------------------------------------------------------
# 主函数
#-------------------------------------------------------------------------------
main() {
local mode="${1:-hourly}"
init
case "$mode" in
hourly)
log "INFO" "Running hourly review..."
local review_result=$(perform_review "hourly")
update_task_queue "$review_result"
generate_claude_tasks "$review_result"
;;
daily)
log "INFO" "Running daily full review..."
local review_result=$(perform_review "daily")
local report=$(generate_daily_report "$review_result")
update_task_queue "$review_result"
generate_claude_tasks "$review_result"
update_knowledge_base
log "INFO" "Daily review completed. Report: $report"
;;
force)
log "WARN" "Running forced full review..."
local review_result=$(perform_review "force")
local report=$(generate_daily_report "$review_result")
update_task_queue "$review_result"
generate_claude_tasks "$review_result"
log "INFO" "Forced review completed. Report: $report"
;;
*)
echo "Usage: $0 [hourly|daily|force]"
exit 1
;;
esac
}
main "$@"