#!/bin/bash # 完整性检查脚本 # 验证 swagger 注解完整性和响应格式统一性 # # 使用方法: # ./scripts/check-integrity.sh # 检查所有 # ./scripts/check-integrity.sh swagger # 只检查 swagger # ./scripts/check-integrity.sh response # 只检查响应格式 set -e RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' ERRORS=0 check_swagger() { echo "=== Swagger 注解完整性检查 ===" local handler_dir="internal/api/handler" local failures=0 for f in "$handler_dir"/*_handler.go; do # Only count methods that take *gin.Context as first param (actual HTTP handlers) local methods=$(grep -E "^func \(h \*[A-Za-z]+.*\) [A-Z].*\(c \*gin\.Context\)" "$f" | wc -l) local annotations=$(grep -c "@Summary" "$f" || echo 0) if [ "$methods" != "$annotations" ]; then echo -e "${RED}FAIL${NC}: $(basename $f) - $methods handler methods, $annotations @Summary annotations" failures=$((failures + 1)) else echo -e "${GREEN}PASS${NC}: $(basename $f) - $methods/$annotations" fi done if [ $failures -gt 0 ]; then echo -e "\n${RED}Swagger 检查失败: $failures 个文件有问题${NC}" ERRORS=$((ERRORS + failures)) else echo -e "\n${GREEN}所有 handler 的 swagger 注解完整${NC}" fi } check_response_format() { echo "" echo "=== 响应格式统一性检查 ===" local failures=0 # 检查直接返回 TokenResponse 或 IntrospectResponse 的情况 # 白名单:OAuth 标准端点(RFC 6749, RFC 7009) # - /api/v1/sso/token (OAuth Token endpoint) - 必须直接返回 TokenResponse # - /api/v1/sso/introspect (OAuth Token Introspection) - 必须直接返回 IntrospectResponse local direct_returns=$(grep -rn "c.JSON.*TokenResponse\|c.JSON.*IntrospectResponse" internal/api/handler/ 2>/dev/null || true) if [ -n "$direct_returns" ]; then # 检查是否都是白名单端点 local non_oauth=0 while IFS=: read -r file line content; do # 这些行是白名单端点,不需要包装 if [[ "$content" == *"TokenResponse"* ]] && [[ "$line" == "213" ]]; then echo -e "${YELLOW}WHITELIST${NC}: $file:$line - OAuth Token endpoint (RFC 6749)" elif [[ "$content" == *"IntrospectResponse"* ]] && [[ "$line" == "257" || "$line" == "261" ]]; then echo -e "${YELLOW}WHITELIST${NC}: $file:$line - OAuth Introspection endpoint (RFC 7009)" else echo -e "${RED}ISSUE${NC}: $file:$line - $content" non_oauth=$((non_oauth + 1)) fi done <<< "$direct_returns" if [ $non_oauth -gt 0 ]; then echo "" echo -e "${RED}发现 $non_oauth 个非 OAuth 端点使用直接返回格式${NC}" failures=$((failures + non_oauth)) else echo "" echo -e "${GREEN}所有直接返回格式都是白名单端点(符合 RFC 标准)${NC}" fi else echo -e "${GREEN}所有 handler 使用统一响应格式${NC}" fi if [ $failures -gt 0 ]; then ERRORS=$((ERRORS + failures)) fi } check_test_types() { echo "" echo "=== 测试基础设施检查 ===" # 检查 IntegrationRedisSuite 是否定义 # 定义存在返回 0,不存在返回 1 if grep -q "type IntegrationRedisSuite struct" internal/repository/*.go 2>/dev/null; then echo -e "${GREEN}IntegrationRedisSuite 类型已定义${NC}" else echo -e "${RED}发现问题: IntegrationRedisSuite 类型未定义${NC}" echo "需要在 internal/repository/ 中定义 IntegrationRedisSuite 类型" ERRORS=$((ERRORS + 1)) fi } check_coverage() { echo "" echo "=== 测试覆盖率验证 ===" local coverage=$(go test ./internal/repository/... -cover -count=1 2>&1 | grep "coverage" | grep -oE "[0-9]+\.[0-9]+%" | head -1) if [ -n "$coverage" ]; then echo -e "${GREEN}Repository 测试覆盖率: $coverage${NC}" else echo -e "${RED}无法获取覆盖率${NC}" ERRORS=$((ERRORS + 1)) fi } # 主逻辑 case "${1:-all}" in swagger) check_swagger ;; response) check_response_format ;; types) check_test_types ;; coverage) check_coverage ;; all) check_swagger check_response_format check_test_types check_coverage ;; *) echo "用法: $0 [swagger|response|types|coverage|all]" exit 1 ;; esac echo "" if [ $ERRORS -gt 0 ]; then echo -e "${RED}完整性检查失败: $ERRORS 个问题${NC}" exit 1 else echo -e "${GREEN}所有完整性检查通过${NC}" exit 0 fi