topfans/backend/scripts/check_status_code_consistency.sh
2026-06-15 16:28:35 +08:00

141 lines
4.7 KiB
Bash
Executable File

#!/bin/bash
# 状态码一致性检查
# 用法: bash scripts/check_status_code_consistency.sh
# 退出码: 0 = 全部通过, 1 = 发现违规
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/.."
echo "=========================================="
echo "状态码一致性检查"
echo "=========================================="
echo ""
FAIL=0
# 1) 禁止后端代码硬编码 HTTP 数字到 BaseResponse.Code 字段
# 应当用 uint32(codes.X) 或 uint32(appErrors.ToGRPCCode(err))
echo "[1/9] 检查硬编码 HTTP 数字到 Code 字段..."
HITS=$(grep -rnE 'Code:\s*[0-9]+|Code:\s*uint32\([0-9]+\)' --include="*.go" services/ gateway/ 2>/dev/null | grep -v "_test\.go" || true)
if [ -n "$HITS" ]; then
echo "❌ 发现硬编码 HTTP 数字:"
echo "$HITS" | head -20
FAIL=1
else
echo " ✅ 无硬编码"
fi
# 2) 禁止老的 StatusCode enum 引用
echo "[2/9] 检查 StatusCode enum 残留..."
HITS=$(grep -rn "StatusCode_STATUS_\|pbCommon\.StatusCode\b" --include="*.go" services/ gateway/ 2>/dev/null | grep -v "_test\.go\|swagger\." || true)
if [ -n "$HITS" ]; then
echo "❌ 发现 StatusCode enum 引用:"
echo "$HITS" | head -10
FAIL=1
else
echo " ✅ 无残留"
fi
# 3) 禁止 ToStatusCode 引用
echo "[3/9] 检查 ToStatusCode 残留..."
HITS=$(grep -rn "appErrors\.ToStatusCode\b" --include="*.go" services/ gateway/ 2>/dev/null | grep -v "_test\.go" || true)
if [ -n "$HITS" ]; then
echo "❌ 发现 ToStatusCode 引用:"
echo "$HITS" | head -10
FAIL=1
else
echo " ✅ 无残留"
fi
# 4) 禁止 codes.<数字> 这种无效引用(应是 codes.OK / codes.Internal 等具名常量)
# 这种错误不会导致 build 失败前的 grep 检查不到,但 build 会 syntax error
echo "[4/9] 检查 codes.<数字> 无效引用..."
HITS=$(grep -rnE 'codes\.[0-9]+' --include="*.go" services/ gateway/ 2>/dev/null | grep -v "_test\.go" || true)
if [ -n "$HITS" ]; then
echo "❌ 发现 codes.<数字> 无效引用:"
echo "$HITS" | head -10
FAIL=1
else
echo " ✅ 无无效引用"
fi
# 5) 后端 Base.Code 比较漏 uint32 wrap
echo "[5/9] 检查 Base.Code 直接 == codes.X (漏 uint32 wrap)..."
HITS=$(grep -rnE 'Base\.Code\s*[=!]+\s*codes\.' --include="*.go" services/ gateway/ 2>/dev/null | grep -v "_test\.go" || true)
if [ -n "$HITS" ]; then
echo "❌ 发现漏 uint32 wrap 的比较:"
echo "$HITS" | head -10
FAIL=1
else
echo " ✅ 无遗漏"
fi
# 6) 后端 Base.Code 直接 == 200 (旧 HTTP 数字)
echo "[6/9] 检查 Base.Code 直接 == 200..."
HITS=$(grep -rnE 'Base\.Code\s*[=!]+\s*200\b' --include="*.go" services/ gateway/ 2>/dev/null | grep -v "_test\.go" || true)
if [ -n "$HITS" ]; then
echo "❌ 发现 Base.Code == 200:"
echo "$HITS" | head -10
FAIL=1
else
echo " ✅ 无残留"
fi
# 7) 前端 code === 200/401/403/400/404/500 等 HTTP 数字(应只剩 === 0/16/7/3/5/8/13)
echo "[7/9] 检查前端 code === HTTP 数字..."
HITS=$(grep -rnE 'code\s*===\s*(200|400|401|403|404|429|500|409)\b|code\s*!==\s*(200|400|401|403|404|429|500|409)\b' \
--include="*.js" --include="*.vue" \
--exclude-dir="unpackage" --exclude-dir="node_modules" --exclude-dir="dist" \
--exclude-dir="uni_modules" --exclude-dir="static" --exclude-dir="common" \
../frontend/ 2>/dev/null || true)
if [ -n "$HITS" ]; then
echo "❌ 发现 HTTP 数字判断:"
echo "$HITS" | head -10
FAIL=1
else
echo " ✅ 无残留"
fi
# 8) 前端 mock data 里的 code: 200/401/...
echo "[8/9] 检查前端 mock data code: <HTTP 数字>..."
HITS=$(grep -rnE 'code:\s*(200|400|401|403|404|429|500|409)\b' \
--include="*.js" --include="*.vue" \
--exclude-dir="unpackage" --exclude-dir="node_modules" --exclude-dir="dist" \
--exclude-dir="uni_modules" --exclude-dir="static" --exclude-dir="common" \
../frontend/ 2>/dev/null || true)
if [ -n "$HITS" ]; then
echo "❌ 发现 mock data HTTP 数字:"
echo "$HITS" | head -10
FAIL=1
else
echo " ✅ 无残留"
fi
# 9) 完整编译验证(覆盖所有 client/service/provider/repository 子包)
# 关键: 必须用 PIPESTATUS[0] 拿 go 命令的真实退出码,不能直接 $?(那是 head 的)
echo "[9/9] 完整编译验证(覆盖所有 client 库)..."
go test -count=1 -run='^$' ./... > /tmp/build_out 2>&1
BUILD_EXIT=$?
if [ $BUILD_EXIT -ne 0 ]; then
echo "❌ 编译失败(退出码 $BUILD_EXIT):"
tail -10 /tmp/build_out
FAIL=1
else
echo " ✅ 全部包编译通过"
fi
echo ""
if [ $FAIL -eq 0 ]; then
echo "=========================================="
echo "✅ 状态码一致性检查全部通过"
echo "=========================================="
exit 0
else
echo "=========================================="
echo "❌ 状态码一致性检查失败"
echo "=========================================="
exit 1
fi