tool-trunk-checker.sh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #!/bin/bash
  2. # 自动运行代码质量检查
  3. # 显示使用说明
  4. show_usage() {
  5. echo "用法: $0 [选项] [文件或目录...]"
  6. echo "选项:"
  7. echo " -a, --all 检查所有文件"
  8. echo " -g, --git [默认] 只检查git相关的文件(已修改、已暂存、未跟踪)"
  9. echo " -f, --file FILE 指定要检查的特定文件"
  10. echo " -d, --dir DIR 指定要检查的目录"
  11. echo " --help 显示此帮助信息"
  12. echo ""
  13. echo "示例:"
  14. echo " $0 # 检查所有git相关文件(默认)"
  15. echo " $0 -f file1.go -f file2.py # 检查指定文件"
  16. echo " $0 -d src/ -d tests/ # 检查指定目录"
  17. echo " $0 file1.go src/ tests/ # 混合指定文件和目录"
  18. }
  19. # 默认模式:检查git相关文件
  20. MODE="git"
  21. # 解析命令行参数
  22. declare -a USER_FILES_ARRAY=()
  23. while [[ $# -gt 0 ]]; do
  24. case $1 in
  25. -a | --all)
  26. MODE="all"
  27. shift
  28. ;;
  29. -g | --git)
  30. MODE="git"
  31. shift
  32. ;;
  33. -f | --file)
  34. MODE="file"
  35. if [ -f "$2" ]; then
  36. USER_FILES_ARRAY+=("$2")
  37. else
  38. echo "警告:文件 '$2' 不存在,跳过"
  39. fi
  40. shift 2
  41. ;;
  42. -d | --dir)
  43. MODE="dir"
  44. if [ -d "$2" ]; then
  45. # 查找目录下的所有文件并添加到数组
  46. while IFS= read -r file; do
  47. [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && USER_FILES_ARRAY+=("${file}")
  48. done < <(find "$2" -type f 2>/dev/null | grep -v '/\.' || true)
  49. else
  50. echo "警告:目录 '$2' 不存在,跳过"
  51. fi
  52. shift 2
  53. ;;
  54. --help)
  55. show_usage
  56. exit 0
  57. ;;
  58. -*)
  59. echo "错误:未知选项 '$1'"
  60. show_usage
  61. exit 1
  62. ;;
  63. *)
  64. # 处理直接指定的文件或目录
  65. MODE="处理直接指定的文件或目录"
  66. if [ -f "$1" ]; then
  67. USER_FILES_ARRAY+=("$1")
  68. elif [ -d "$1" ]; then
  69. # 查找目录下的所有文件并添加到数组
  70. while IFS= read -r file; do
  71. [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && USER_FILES_ARRAY+=("${file}")
  72. done < <(find "$1" -type f 2>/dev/null | grep -v '/\.' || true)
  73. else
  74. echo "警告:'$1' 不是文件或目录,跳过"
  75. fi
  76. shift
  77. ;;
  78. esac
  79. done
  80. # 将数组转换为换行分隔的字符串
  81. if [ ${#USER_FILES_ARRAY[@]} -gt 0 ]; then
  82. USER_FILES=$(printf "%s\n" "${USER_FILES_ARRAY[@]}")
  83. else
  84. USER_FILES=""
  85. fi
  86. echo ""
  87. echo "🚀 正在运行代码质量检查..."
  88. echo "========================================"
  89. echo "模式: ${MODE}"
  90. # 切换到工作目录(文件收集阶段;实际运行 trunk 前会再切到目标仓库根)
  91. cd /workspace || exit
  92. # 解析 trunk 二进制(优先级:TRUNK_BIN 环境变量 > /workspace/trunk > PATH 中的 trunk)
  93. resolve_trunk() {
  94. if [[ -n ${TRUNK_BIN-} ]] && [[ -x ${TRUNK_BIN} ]]; then
  95. printf '%s\n' "${TRUNK_BIN}"
  96. elif [[ -x /workspace/trunk ]]; then
  97. printf '%s\n' /workspace/trunk
  98. elif command -v trunk >/dev/null 2>&1; then
  99. command -v trunk
  100. else
  101. printf '\n'
  102. fi
  103. }
  104. TRUNK_BIN="$(resolve_trunk)"
  105. if [[ -z ${TRUNK_BIN} ]]; then
  106. echo "❌ trunk工具未找到,请设置 TRUNK_BIN 或安装 trunk"
  107. exit 1
  108. fi
  109. # 根据模式获取需要检查的文件
  110. if [ "${MODE}" = "all" ]; then
  111. # 检查所有文件
  112. ALL_FILES=$(find . -type f 2>/dev/null | grep -v '/\.' | grep -v '^/\.' | sort | uniq || true)
  113. elif [ -n "${USER_FILES}" ]; then
  114. # 使用用户指定的文件
  115. ALL_FILES="${USER_FILES}"
  116. else
  117. # 默认:检查git相关文件
  118. STAGED_FILES=$(git diff --name-only --diff-filter=d 2>/dev/null || true)
  119. NEW_FILES=$(git diff --cached --name-only --diff-filter=A 2>/dev/null || true)
  120. UNTRACKED_FILES=$(git ls-files --others --exclude-standard 2>/dev/null || true)
  121. # 使用数组安全地合并文件列表
  122. declare -a ALL_FILES_ARRAY=()
  123. # 添加已修改的文件
  124. if [ -n "${STAGED_FILES}" ]; then
  125. while IFS= read -r file; do
  126. [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && ALL_FILES_ARRAY+=("${file}")
  127. done <<<"${STAGED_FILES}"
  128. fi
  129. # 添加新暂存的文件
  130. if [ -n "${NEW_FILES}" ]; then
  131. while IFS= read -r file; do
  132. [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && ALL_FILES_ARRAY+=("${file}")
  133. done <<<"${NEW_FILES}"
  134. fi
  135. # 添加未跟踪的文件
  136. if [ -n "${UNTRACKED_FILES}" ]; then
  137. while IFS= read -r file; do
  138. [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && ALL_FILES_ARRAY+=("${file}")
  139. done <<<"${UNTRACKED_FILES}"
  140. fi
  141. # 去重并生成最终文件列表
  142. if [ ${#ALL_FILES_ARRAY[@]} -gt 0 ]; then
  143. ALL_FILES=$(printf "%s\n" "${ALL_FILES_ARRAY[@]}" | sort | uniq || true)
  144. else
  145. ALL_FILES=""
  146. fi
  147. fi
  148. # 去重并过滤空行和隐藏文件(仅在all模式下过滤隐藏文件)
  149. if [ "${MODE}" = "all" ] || [ -n "${USER_FILES}" ]; then
  150. # 始终过滤空行并去重
  151. ALL_FILES=$(echo "${ALL_FILES}" | grep -v '^$' | sort | uniq || true)
  152. # 仅在all模式下过滤隐藏文件(用户明确指定文件时不过滤)
  153. if [ "${MODE}" = "all" ]; then
  154. ALL_FILES=$(echo "${ALL_FILES}" | grep -v '/\.' | grep -v '^/\.' || true)
  155. fi
  156. fi
  157. if [ -z "${ALL_FILES}" ]; then
  158. echo "ℹ️ 没有找到需要检查的文件"
  159. exit 0
  160. fi
  161. # 检查文件数量
  162. FILE_COUNT=$(echo "${ALL_FILES}" | wc -l)
  163. echo ""
  164. echo "📊 共发现 ${FILE_COUNT} 个需要检查的文件:"
  165. echo "${ALL_FILES}"
  166. echo ""
  167. # 确定目标所在的 git 仓库根并切换(子模块是独立 git 仓库,需在各自仓库根运行 trunk)
  168. if [[ -n ${ALL_FILES} ]]; then
  169. FIRST_FILE="$(printf '%s\n' "${ALL_FILES}" | head -n 1)"
  170. REPO_ROOT="$(git -C "$(dirname "${FIRST_FILE}")" rev-parse --show-toplevel 2>/dev/null || echo /workspace)"
  171. else
  172. REPO_ROOT="/workspace"
  173. fi
  174. cd "${REPO_ROOT}" || exit
  175. # 运行trunk check检查代码质量(已禁用安全扫描类工具,仅纯代码质量/格式检查)
  176. echo ""
  177. echo "🔍 正在运行代码质量检查..."
  178. if ! "${TRUNK_BIN}" check ${ALL_FILES}; then
  179. echo ""
  180. echo "❌ 代码质量检查失败!"
  181. echo ""
  182. echo "请修复上述问题后再提交"
  183. echo ""
  184. exit 1
  185. fi
  186. echo ""
  187. echo "✅ 代码质量检查通过!可以安全提交。"
  188. echo "========================================"
  189. echo ""
  190. exit 0