Files
MyGoNavi/tools/detect-changed-driver-agents.sh
Syngnat 992d2dee45 feat(iris): 新增 InterSystems IRIS 数据源支持
- 后端新增 IRIS 连接、查询、DDL、索引元数据和 DataGrid 编辑能力
- 接入 optional driver-agent、构建标签、revision 生成和变更检测流程
- 前端新增 IRIS 连接入口、方言映射、能力配置和图标展示
- 修复 IRIS 主键识别、事务开启错误处理和驱动连接关闭问题
- 补充后端、前端和构建脚本相关回归测试
Refs #408
2026-05-17 10:32:08 +08:00

394 lines
9.5 KiB
Bash
Raw 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.
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$SCRIPT_DIR"
SCRIPT_DIR_WINDOWS="$(pwd -W 2>/dev/null || true)"
SCRIPT_DIR_WINDOWS="${SCRIPT_DIR_WINDOWS//\\//}"
DEFAULT_DRIVERS=(mariadb oceanbase doris starrocks sphinx sqlserver sqlite duckdb dameng kingbase highgo vastbase opengauss iris mongodb tdengine clickhouse)
TARGET_PLATFORMS=(darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64)
usage() {
cat <<'EOF'
用法:
./tools/detect-changed-driver-agents.sh --base <ref> [--head <ref>]
输出:
逗号分隔的 driver-agent 列表;没有 driver-agent 相关变更时输出空行。
说明:
通过 go list -deps 计算每个 driver-agent 的真实源码依赖,再与 git diff 文件求交集。
如果无法解析基准或依赖分析失败,会保守输出全部 driver。
EOF
}
join_drivers() {
local IFS=,
echo "$*"
}
all_drivers_csv() {
join_drivers "${DEFAULT_DRIVERS[@]}"
}
is_dependency_source_file() {
case "$1" in
*.go|*.c|*.cc|*.cpp|*.cxx|*.h|*.hpp|*.m|*.mm|*.s|*.S|*.syso)
return 0
;;
*)
return 1
;;
esac
}
normalize_driver() {
local value
value="$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')"
case "$value" in
doris|diros) echo "doris" ;;
open_gauss|open-gauss) echo "opengauss" ;;
mariadb|oceanbase|starrocks|sphinx|sqlserver|sqlite|duckdb|dameng|kingbase|highgo|vastbase|opengauss|iris|mongodb|tdengine|clickhouse)
echo "$value"
;;
*)
return 1
;;
esac
}
build_driver_name() {
case "$1" in
doris) echo "diros" ;;
*) echo "$1" ;;
esac
}
driver_build_tags() {
local driver="$1"
local platform="$2"
local goos="${platform%%/*}"
local goarch="${platform##*/}"
local build_driver tag
build_driver="$(build_driver_name "$driver")"
tag="gonavi_${build_driver}_driver"
if [[ "$driver" == "duckdb" && "$goos" == "windows" && "$goarch" == "amd64" ]]; then
tag="$tag duckdb_use_lib"
fi
echo "$tag"
}
all_driver_build_tags() {
local platform="$1"
local -a tags=()
local driver
for driver in "${DEFAULT_DRIVERS[@]}"; do
tags+=("$(driver_build_tags "$driver" "$platform")")
done
local IFS=" "
echo "${tags[*]}"
}
driver_cgo_enabled() {
# Detection only needs the Go dependency graph; keeping CGO off avoids
# cross-platform cgo toolchain requirements in the Ubuntu detection job.
echo 0
}
relative_repo_path() {
local path="$1"
path="${path//\\//}"
case "$path" in
"$SCRIPT_DIR"/*)
path="${path#$SCRIPT_DIR/}"
;;
esac
if [[ -n "$SCRIPT_DIR_WINDOWS" ]]; then
case "$path" in
"$SCRIPT_DIR_WINDOWS"/*)
path="${path#$SCRIPT_DIR_WINDOWS/}"
;;
esac
fi
path="${path#./}"
printf '%s\n' "$path"
}
add_analysis_platform() {
local platform="$1"
if [[ "$analysis_platform_seen" == *"|$platform|"* ]]; then
return 0
fi
analysis_platforms+=("$platform")
analysis_platform_seen="${analysis_platform_seen}${platform}|"
}
add_forced_driver() {
local driver
driver="$(normalize_driver "$1")" || return 0
if [[ "$forced_driver_seen" == *"|$driver|"* ]]; then
return 0
fi
forced_changed_drivers+=("$driver")
forced_driver_seen="${forced_driver_seen}${driver}|"
}
list_dependency_files() {
local tags="$1"
local cgo_enabled="$2"
local goos="$3"
local goarch="$4"
local output="$5"
CGO_ENABLED="$cgo_enabled" GOOS="$goos" GOARCH="$goarch" GOTOOLCHAIN=auto \
go list -deps \
-tags "$tags" \
-f '{{if and (not .Standard) .Module.Main}}{{range .GoFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{range .CgoFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{range .CFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{range .CXXFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{range .MFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{range .HFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{range .SFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{range .SysoFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{end}}' \
./cmd/optional-driver-agent | sort -u >"$output"
}
dependency_union_contains_changed_files() {
local platform goos goarch tags tmp file rel
local matched_any=false
for platform in "${TARGET_PLATFORMS[@]}"; do
goos="${platform%%/*}"
goarch="${platform##*/}"
tags="$(all_driver_build_tags "$platform")"
tmp="$(mktemp "${TMPDIR:-/tmp}/gonavi-driver-dep-union.XXXXXX")"
if ! list_dependency_files "$tags" 0 "$goos" "$goarch" "$tmp"; then
rm -f "$tmp"
return 2
fi
while IFS= read -r file; do
[[ -n "$file" ]] || continue
rel="$(relative_repo_path "$file")"
if [[ -n "${changed_file_set[$rel]:-}" ]]; then
dependency_matched_platforms["$rel"]="${dependency_matched_platforms[$rel]:-}|$platform|"
matched_any=true
fi
done <"$tmp"
rm -f "$tmp"
done
if [[ "$matched_any" == "true" ]]; then
return 0
fi
return 1
}
base_ref=""
head_ref="HEAD"
while [[ $# -gt 0 ]]; do
case "$1" in
--base)
base_ref="${2:-}"
shift 2
;;
--head)
head_ref="${2:-}"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
echo "未知参数:$1" >&2
usage >&2
exit 1
;;
esac
done
if [[ -z "$base_ref" ]]; then
echo "缺少 --base 参数。" >&2
usage >&2
exit 1
fi
if [[ "$base_ref" == "all" ]]; then
all_drivers_csv
exit 0
fi
if ! git rev-parse --verify "${head_ref}^{commit}" >/dev/null 2>&1; then
echo "无法解析 head ref$head_ref" >&2
exit 1
fi
head_commit="$(git rev-parse "${head_ref}^{commit}")"
if ! git rev-parse --verify "${base_ref}^{commit}" >/dev/null 2>&1; then
echo "无法解析 base ref$base_ref;保守构建全部 driver-agent。" >&2
all_drivers_csv
exit 0
fi
base_commit="$(git rev-parse "${base_ref}^{commit}")"
declare -A changed_file_set=()
while IFS= read -r -d '' file; do
file="$(relative_repo_path "$file")"
[[ -n "$file" ]] || continue
changed_file_set["$file"]=1
done < <(git diff --name-only -z "$base_commit" "$head_commit")
if [[ ${#changed_file_set[@]} -eq 0 ]]; then
echo ""
exit 0
fi
for file in "${!changed_file_set[@]}"; do
case "$file" in
go.mod|go.sum|build-driver-agents.sh|tools/compress-driver-artifact.sh|tools/generate-driver-agent-revisions.sh|tools/detect-changed-driver-agents.sh)
all_drivers_csv
exit 0
;;
esac
done
declare -a forced_changed_drivers=()
forced_driver_seen="|"
for file in "${!changed_file_set[@]}"; do
case "$file" in
internal/db/duckdb_*.go)
add_forced_driver duckdb
;;
esac
done
has_source_candidate=false
for file in "${!changed_file_set[@]}"; do
if is_dependency_source_file "$file"; then
has_source_candidate=true
break
fi
done
if [[ "$has_source_candidate" != "true" ]]; then
echo ""
exit 0
fi
while IFS= read -r -d '' file; do
file="$(relative_repo_path "$file")"
if is_dependency_source_file "$file"; then
echo "检测到源码依赖候选文件被删除;保守构建全部 driver-agent$file" >&2
all_drivers_csv
exit 0
fi
done < <(git diff --name-only --diff-filter=D -z "$base_commit" "$head_commit")
declare -A dependency_matched_platforms=()
set +e
dependency_union_contains_changed_files
dependency_union_status=$?
set -e
case "$dependency_union_status" in
0)
;;
1)
if [[ ${#forced_changed_drivers[@]} -eq 0 ]]; then
echo ""
exit 0
fi
;;
*)
echo "分析 driver-agent 依赖全集失败;保守构建全部 driver-agent。" >&2
all_drivers_csv
exit 0
;;
esac
declare -a analysis_platforms=()
analysis_platform_seen="|"
for file in "${!dependency_matched_platforms[@]}"; do
matched_platforms="${dependency_matched_platforms[$file]}"
if [[ "$matched_platforms" == *"|linux/amd64|"* ]]; then
add_analysis_platform "linux/amd64"
continue
fi
for platform in "${TARGET_PLATFORMS[@]}"; do
if [[ "$matched_platforms" == *"|$platform|"* ]]; then
add_analysis_platform "$platform"
fi
done
done
if [[ ${#analysis_platforms[@]} -eq 0 ]]; then
analysis_platforms=("${TARGET_PLATFORMS[@]}")
fi
declare -a changed_drivers=()
driver_seen="|"
add_driver() {
local driver
driver="$(normalize_driver "$1")" || return 0
if [[ "$driver_seen" == *"|$driver|"* ]]; then
return 0
fi
changed_drivers+=("$driver")
driver_seen="${driver_seen}${driver}|"
}
for driver in "${forced_changed_drivers[@]}"; do
add_driver "$driver"
done
driver_depends_on_changed_files() {
local driver="$1"
local platform="$2"
local goos="${platform%%/*}"
local goarch="${platform##*/}"
local tags cgo_enabled file rel tmp
tags="$(driver_build_tags "$driver" "$platform")"
cgo_enabled="$(driver_cgo_enabled "$driver")"
tmp="$(mktemp "${TMPDIR:-/tmp}/gonavi-driver-deps.XXXXXX")"
if ! list_dependency_files "$tags" "$cgo_enabled" "$goos" "$goarch" "$tmp"; then
rm -f "$tmp"
return 2
fi
while IFS= read -r file; do
[[ -n "$file" ]] || continue
rel="$(relative_repo_path "$file")"
if [[ -n "${changed_file_set[$rel]:-}" ]]; then
rm -f "$tmp"
return 0
fi
done <"$tmp"
rm -f "$tmp"
return 1
}
for driver in "${DEFAULT_DRIVERS[@]}"; do
driver_changed=false
for platform in "${analysis_platforms[@]}"; do
set +e
driver_depends_on_changed_files "$driver" "$platform"
status=$?
set -e
case "$status" in
0)
add_driver "$driver"
driver_changed=true
break
;;
1)
;;
*)
echo "分析 $driver driver-agent 依赖失败;保守构建全部 driver-agent。" >&2
all_drivers_csv
exit 0
;;
esac
done
done
join_drivers "${changed_drivers[@]}"