#!/bin/bash # 自动运行代码质量检查 # 显示使用说明 show_usage() { echo "用法: $0 [选项] [文件或目录...]" echo "选项:" echo " -a, --all 检查所有文件" echo " -g, --git [默认] 只检查git相关的文件(已修改、已暂存、未跟踪)" echo " -f, --file FILE 指定要检查的特定文件" echo " -d, --dir DIR 指定要检查的目录" echo " --help 显示此帮助信息" echo "" echo "示例:" echo " $0 # 检查所有git相关文件(默认)" echo " $0 -f file1.go -f file2.py # 检查指定文件" echo " $0 -d src/ -d tests/ # 检查指定目录" echo " $0 file1.go src/ tests/ # 混合指定文件和目录" } # 默认模式:检查git相关文件 MODE="git" # 解析命令行参数 declare -a USER_FILES_ARRAY=() while [[ $# -gt 0 ]]; do case $1 in -a | --all) MODE="all" shift ;; -g | --git) MODE="git" shift ;; -f | --file) MODE="file" if [ -f "$2" ]; then USER_FILES_ARRAY+=("$2") else echo "警告:文件 '$2' 不存在,跳过" fi shift 2 ;; -d | --dir) MODE="dir" if [ -d "$2" ]; then # 查找目录下的所有文件并添加到数组 while IFS= read -r file; do [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && USER_FILES_ARRAY+=("${file}") done < <(find "$2" -type f 2>/dev/null | grep -v '/\.' || true) else echo "警告:目录 '$2' 不存在,跳过" fi shift 2 ;; --help) show_usage exit 0 ;; -*) echo "错误:未知选项 '$1'" show_usage exit 1 ;; *) # 处理直接指定的文件或目录 MODE="处理直接指定的文件或目录" if [ -f "$1" ]; then USER_FILES_ARRAY+=("$1") elif [ -d "$1" ]; then # 查找目录下的所有文件并添加到数组 while IFS= read -r file; do [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && USER_FILES_ARRAY+=("${file}") done < <(find "$1" -type f 2>/dev/null | grep -v '/\.' || true) else echo "警告:'$1' 不是文件或目录,跳过" fi shift ;; esac done # 将数组转换为换行分隔的字符串 if [ ${#USER_FILES_ARRAY[@]} -gt 0 ]; then USER_FILES=$(printf "%s\n" "${USER_FILES_ARRAY[@]}") else USER_FILES="" fi echo "" echo "🚀 正在运行代码质量检查..." echo "========================================" echo "模式: ${MODE}" # 切换到工作目录(文件收集阶段;实际运行 trunk 前会再切到目标仓库根) cd /workspace || exit # 解析 trunk 二进制(优先级:TRUNK_BIN 环境变量 > /workspace/trunk > PATH 中的 trunk) resolve_trunk() { if [[ -n ${TRUNK_BIN-} ]] && [[ -x ${TRUNK_BIN} ]]; then printf '%s\n' "${TRUNK_BIN}" elif [[ -x /workspace/trunk ]]; then printf '%s\n' /workspace/trunk elif command -v trunk >/dev/null 2>&1; then command -v trunk else printf '\n' fi } TRUNK_BIN="$(resolve_trunk)" if [[ -z ${TRUNK_BIN} ]]; then echo "❌ trunk工具未找到,请设置 TRUNK_BIN 或安装 trunk" exit 1 fi # 根据模式获取需要检查的文件 if [ "${MODE}" = "all" ]; then # 检查所有文件 ALL_FILES=$(find . -type f 2>/dev/null | grep -v '/\.' | grep -v '^/\.' | sort | uniq || true) elif [ -n "${USER_FILES}" ]; then # 使用用户指定的文件 ALL_FILES="${USER_FILES}" else # 默认:检查git相关文件 STAGED_FILES=$(git diff --name-only --diff-filter=d 2>/dev/null || true) NEW_FILES=$(git diff --cached --name-only --diff-filter=A 2>/dev/null || true) UNTRACKED_FILES=$(git ls-files --others --exclude-standard 2>/dev/null || true) # 使用数组安全地合并文件列表 declare -a ALL_FILES_ARRAY=() # 添加已修改的文件 if [ -n "${STAGED_FILES}" ]; then while IFS= read -r file; do [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && ALL_FILES_ARRAY+=("${file}") done <<<"${STAGED_FILES}" fi # 添加新暂存的文件 if [ -n "${NEW_FILES}" ]; then while IFS= read -r file; do [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && ALL_FILES_ARRAY+=("${file}") done <<<"${NEW_FILES}" fi # 添加未跟踪的文件 if [ -n "${UNTRACKED_FILES}" ]; then while IFS= read -r file; do [ -n "${file}" ] && [[ ${file} != */.* ]] && [[ ${file} != .* ]] && ALL_FILES_ARRAY+=("${file}") done <<<"${UNTRACKED_FILES}" fi # 去重并生成最终文件列表 if [ ${#ALL_FILES_ARRAY[@]} -gt 0 ]; then ALL_FILES=$(printf "%s\n" "${ALL_FILES_ARRAY[@]}" | sort | uniq || true) else ALL_FILES="" fi fi # 去重并过滤空行和隐藏文件(仅在all模式下过滤隐藏文件) if [ "${MODE}" = "all" ] || [ -n "${USER_FILES}" ]; then # 始终过滤空行并去重 ALL_FILES=$(echo "${ALL_FILES}" | grep -v '^$' | sort | uniq || true) # 仅在all模式下过滤隐藏文件(用户明确指定文件时不过滤) if [ "${MODE}" = "all" ]; then ALL_FILES=$(echo "${ALL_FILES}" | grep -v '/\.' | grep -v '^/\.' || true) fi fi if [ -z "${ALL_FILES}" ]; then echo "ℹ️ 没有找到需要检查的文件" exit 0 fi # 检查文件数量 FILE_COUNT=$(echo "${ALL_FILES}" | wc -l) echo "" echo "📊 共发现 ${FILE_COUNT} 个需要检查的文件:" echo "${ALL_FILES}" echo "" # 确定目标所在的 git 仓库根并切换(子模块是独立 git 仓库,需在各自仓库根运行 trunk) if [[ -n ${ALL_FILES} ]]; then FIRST_FILE="$(printf '%s\n' "${ALL_FILES}" | head -n 1)" REPO_ROOT="$(git -C "$(dirname "${FIRST_FILE}")" rev-parse --show-toplevel 2>/dev/null || echo /workspace)" else REPO_ROOT="/workspace" fi cd "${REPO_ROOT}" || exit # 运行trunk check检查代码质量(已禁用安全扫描类工具,仅纯代码质量/格式检查) echo "" echo "🔍 正在运行代码质量检查..." if ! "${TRUNK_BIN}" check ${ALL_FILES}; then echo "" echo "❌ 代码质量检查失败!" echo "" echo "请修复上述问题后再提交" echo "" exit 1 fi echo "" echo "✅ 代码质量检查通过!可以安全提交。" echo "========================================" echo "" exit 0