mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-26 00:11:43 +08:00
🔧 chore(driver): 自动生成驱动代理 revision
- 新增脚本按 optional driver-agent 源码依赖生成 revision 指纹 - 构建脚本与 dev/release workflow 在打包前自动刷新 revision - 生成驱动 revision 映射并补充 optional driver 覆盖校验
This commit is contained in:
1
.github/workflows/dev-build.yml
vendored
1
.github/workflows/dev-build.yml
vendored
@@ -246,6 +246,7 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
DEV_VERSION="${{ steps.version.outputs.version }}"
|
||||
./tools/generate-driver-agent-revisions.sh --platform "${{ matrix.platform }}"
|
||||
if [ -n "${{ matrix.wails_tags }}" ]; then
|
||||
wails build -platform ${{ matrix.platform }} -clean -o ${{ matrix.build_name }} -tags "${{ matrix.wails_tags }}" -ldflags "-s -w -X GoNavi-Wails/internal/app.AppVersion=${DEV_VERSION}"
|
||||
else
|
||||
|
||||
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -237,6 +237,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
./tools/generate-driver-agent-revisions.sh --platform "${{ matrix.platform }}"
|
||||
if [ -n "${{ matrix.wails_tags }}" ]; then
|
||||
wails build -platform ${{ matrix.platform }} -clean -o ${{ matrix.build_name }} -tags "${{ matrix.wails_tags }}" -ldflags "-s -w -X GoNavi-Wails/internal/app.AppVersion=${{ github.ref_name }}"
|
||||
else
|
||||
|
||||
@@ -152,6 +152,8 @@ echo "🚀 开始构建 optional-driver-agent"
|
||||
echo " 平台:$goos/$goarch"
|
||||
echo " 输出目录:$output_dir_abs"
|
||||
echo " 驱动列表:${drivers[*]}"
|
||||
echo "🧭 生成 driver-agent revision 指纹"
|
||||
"$SCRIPT_DIR/tools/generate-driver-agent-revisions.sh" --platform "$target_platform"
|
||||
|
||||
for driver in "${drivers[@]}"; do
|
||||
if [[ "$driver" == "duckdb" && "$goos" == "windows" && "$goarch" != "amd64" ]]; then
|
||||
|
||||
@@ -155,6 +155,7 @@ package_macos_release() {
|
||||
local archive_suffix="$2"
|
||||
|
||||
echo -e "${GREEN}🍎 正在构建 macOS (${platform})...${NC}"
|
||||
generate_driver_agent_revisions "darwin/${platform}"
|
||||
wails build -platform "darwin/${platform}" -clean -ldflags "$LDFLAGS"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "${RED} ❌ macOS ${platform} 构建失败。${NC}"
|
||||
@@ -185,6 +186,12 @@ package_macos_release() {
|
||||
echo " ✅ 已生成 $zip_name"
|
||||
}
|
||||
|
||||
generate_driver_agent_revisions() {
|
||||
local platform="$1"
|
||||
echo " 🧭 正在生成 driver-agent revision 指纹 (${platform})..."
|
||||
./tools/generate-driver-agent-revisions.sh --platform "$platform"
|
||||
}
|
||||
|
||||
echo -e "${GREEN}🚀 开始构建 $APP_NAME $VERSION...${NC}"
|
||||
|
||||
# 清理并创建输出目录
|
||||
@@ -197,6 +204,7 @@ package_macos_release "amd64" "mac-amd64"
|
||||
# --- Windows AMD64 构建 ---
|
||||
echo -e "${GREEN}🪟 正在构建 Windows (amd64)...${NC}"
|
||||
if command -v x86_64-w64-mingw32-gcc &> /dev/null; then
|
||||
generate_driver_agent_revisions "windows/amd64"
|
||||
wails build -platform windows/amd64 -clean -ldflags "$LDFLAGS"
|
||||
if [ $? -eq 0 ]; then
|
||||
TARGET_EXE="$DIST_DIR/${APP_NAME}-${VERSION}-windows-amd64.exe"
|
||||
@@ -213,6 +221,7 @@ fi
|
||||
# --- Windows ARM64 构建 ---
|
||||
echo -e "${GREEN}🪟 正在构建 Windows (arm64)...${NC}"
|
||||
if command -v aarch64-w64-mingw32-gcc &> /dev/null; then
|
||||
generate_driver_agent_revisions "windows/arm64"
|
||||
wails build -platform windows/arm64 -clean -ldflags "$LDFLAGS"
|
||||
if [ $? -eq 0 ]; then
|
||||
TARGET_EXE="$DIST_DIR/${APP_NAME}-${VERSION}-windows-arm64.exe"
|
||||
@@ -235,6 +244,7 @@ CURRENT_ARCH=$(uname -m)
|
||||
|
||||
if [ "$CURRENT_OS" = "Linux" ] && [ "$CURRENT_ARCH" = "x86_64" ]; then
|
||||
# 本机 Linux amd64,直接构建
|
||||
generate_driver_agent_revisions "linux/amd64"
|
||||
wails build -platform linux/amd64 -clean -ldflags "$LDFLAGS"
|
||||
if [ $? -eq 0 ]; then
|
||||
TARGET_LINUX_BIN="$DIST_DIR/${APP_NAME}-${VERSION}-linux-amd64"
|
||||
@@ -255,6 +265,7 @@ elif command -v x86_64-linux-gnu-gcc &> /dev/null; then
|
||||
export CC=x86_64-linux-gnu-gcc
|
||||
export CXX=x86_64-linux-gnu-g++
|
||||
export CGO_ENABLED=1
|
||||
generate_driver_agent_revisions "linux/amd64"
|
||||
wails build -platform linux/amd64 -clean -ldflags "$LDFLAGS"
|
||||
if [ $? -eq 0 ]; then
|
||||
TARGET_LINUX_BIN="$DIST_DIR/${APP_NAME}-${VERSION}-linux-amd64"
|
||||
@@ -279,6 +290,7 @@ fi
|
||||
echo -e "${GREEN}🐧 正在构建 Linux (arm64)...${NC}"
|
||||
if [ "$CURRENT_OS" = "Linux" ] && [ "$CURRENT_ARCH" = "aarch64" ]; then
|
||||
# 本机 Linux arm64,直接构建
|
||||
generate_driver_agent_revisions "linux/arm64"
|
||||
wails build -platform linux/arm64 -clean -ldflags "$LDFLAGS"
|
||||
if [ $? -eq 0 ]; then
|
||||
TARGET_LINUX_BIN="$DIST_DIR/${APP_NAME}-${VERSION}-linux-arm64"
|
||||
@@ -298,6 +310,7 @@ elif command -v aarch64-linux-gnu-gcc &> /dev/null; then
|
||||
export CC=aarch64-linux-gnu-gcc
|
||||
export CXX=aarch64-linux-gnu-g++
|
||||
export CGO_ENABLED=1
|
||||
generate_driver_agent_revisions "linux/arm64"
|
||||
wails build -platform linux/arm64 -clean -ldflags "$LDFLAGS"
|
||||
if [ $? -eq 0 ]; then
|
||||
TARGET_LINUX_BIN="$DIST_DIR/${APP_NAME}-${VERSION}-linux-arm64"
|
||||
|
||||
21
internal/db/driver_agent_revisions_gen.go
Normal file
21
internal/db/driver_agent_revisions_gen.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Code generated by tools/generate-driver-agent-revisions.sh; DO NOT EDIT.
|
||||
|
||||
package db
|
||||
|
||||
func init() {
|
||||
optionalDriverAgentRevisions = map[string]string{
|
||||
"mariadb": "src-d6c5c6717338834c",
|
||||
"diros": "src-ed4f0f64ed28d3fa",
|
||||
"sphinx": "src-f52324f0a812d7c8",
|
||||
"sqlserver": "src-ec165f18de9cd8b3",
|
||||
"sqlite": "src-9dea6c76bc931114",
|
||||
"duckdb": "src-14027ac1de3c50c7",
|
||||
"dameng": "src-1a08880ff5bbcf31",
|
||||
"kingbase": "src-28eed0e4d942b724",
|
||||
"highgo": "src-76146bf97f07f25c",
|
||||
"vastbase": "src-555b60c4863542b6",
|
||||
"mongodb": "src-2540a7350c4243aa",
|
||||
"tdengine": "src-ce3e4a9c46f6b92d",
|
||||
"clickhouse": "src-78e5ada4da56704d",
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,11 @@ var optionalGoDrivers = map[string]struct{}{
|
||||
"clickhouse": {},
|
||||
}
|
||||
|
||||
// optionalDriverAgentRevisions 记录 GoNavi 对各可选 driver-agent 包装逻辑的兼容版本。
|
||||
// 该 map 由 tools/generate-driver-agent-revisions.sh 按 driver-agent 源码依赖自动生成,
|
||||
// 避免人工判断需要 bump 哪个驱动 revision。
|
||||
var optionalDriverAgentRevisions = map[string]string{}
|
||||
|
||||
var (
|
||||
externalDriverDirMu sync.RWMutex
|
||||
externalDriverDir string
|
||||
@@ -105,6 +110,10 @@ func IsOptionalGoDriverBuildIncluded(driverType string) bool {
|
||||
return optionalGoDriverBuildIncluded(normalizeRuntimeDriverType(driverType))
|
||||
}
|
||||
|
||||
func OptionalDriverAgentRevision(driverType string) string {
|
||||
return strings.TrimSpace(optionalDriverAgentRevisions[normalizeRuntimeDriverType(driverType)])
|
||||
}
|
||||
|
||||
// IsBuiltinDriver 返回指定驱动类型是否为核心内置驱动(始终可用,无需安装)。
|
||||
func IsBuiltinDriver(driverType string) bool {
|
||||
_, ok := coreBuiltinDrivers[normalizeRuntimeDriverType(driverType)]
|
||||
|
||||
@@ -31,6 +31,17 @@ func TestBuiltinLikeDriversRemainAvailable(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionalDriverAgentRevisionsGeneratedForOptionalDrivers(t *testing.T) {
|
||||
for driverType := range optionalGoDrivers {
|
||||
if revision := OptionalDriverAgentRevision(driverType); revision == "" {
|
||||
t.Fatalf("%s 缺少自动生成的 driver-agent revision", driverType)
|
||||
}
|
||||
}
|
||||
if OptionalDriverAgentRevision("doris") != OptionalDriverAgentRevision("diros") {
|
||||
t.Fatalf("doris/diros revision 应归一一致")
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagedDriverRequiresInstallMarker(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
SetExternalDriverDownloadDirectory(tmpDir)
|
||||
|
||||
251
tools/generate-driver-agent-revisions.sh
Executable file
251
tools/generate-driver-agent-revisions.sh
Executable file
@@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
DEFAULT_DRIVERS=(mariadb diros sphinx sqlserver sqlite duckdb dameng kingbase highgo vastbase mongodb tdengine clickhouse)
|
||||
OUTPUT_FILE="internal/db/driver_agent_revisions_gen.go"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
用法:
|
||||
./tools/generate-driver-agent-revisions.sh [选项]
|
||||
|
||||
选项:
|
||||
--platform <GOOS/GOARCH> 按目标平台解析 Go build tags,默认使用当前 Go 环境
|
||||
--drivers <列表> 指定驱动列表(逗号分隔),默认生成所有 optional driver
|
||||
-h, --help 显示帮助
|
||||
EOF
|
||||
}
|
||||
|
||||
normalize_driver() {
|
||||
local value
|
||||
value="$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')"
|
||||
case "$value" in
|
||||
doris|diros) echo "diros" ;;
|
||||
mariadb|diros|sphinx|sqlserver|sqlite|duckdb|dameng|kingbase|highgo|vastbase|mongodb|tdengine|clickhouse)
|
||||
echo "$value"
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
build_driver_name() {
|
||||
echo "$1"
|
||||
}
|
||||
|
||||
hash_file() {
|
||||
local target="$1"
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$target" | awk '{print $1}'
|
||||
return
|
||||
fi
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
shasum -a 256 "$target" | awk '{print $1}'
|
||||
return
|
||||
fi
|
||||
echo "未找到 sha256sum 或 shasum" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
should_include_internal_db_file() {
|
||||
local driver="$1"
|
||||
local identity="$2"
|
||||
|
||||
case "$identity" in
|
||||
internal/db/agent_process_stub.go|\
|
||||
internal/db/agent_process_windows.go|\
|
||||
internal/db/database.go|\
|
||||
internal/db/database_optional_factories_full.go|\
|
||||
internal/db/database_optional_factories_lite.go|\
|
||||
internal/db/driver_agent_binary_check.go|\
|
||||
internal/db/driver_support.go|\
|
||||
internal/db/json_decode.go|\
|
||||
internal/db/mysql_agent_path.go|\
|
||||
internal/db/optional_driver_agent_impl.go|\
|
||||
internal/db/optional_driver_build_full.go|\
|
||||
internal/db/optional_driver_build_lite.go|\
|
||||
internal/db/query_value.go|\
|
||||
internal/db/scan_rows.go|\
|
||||
internal/db/ssl_mode.go|\
|
||||
internal/db/timeout.go)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$driver:$identity" in
|
||||
mariadb:internal/db/mariadb_impl.go|\
|
||||
diros:internal/db/diros_impl.go|\
|
||||
diros:internal/db/mysql_impl.go|\
|
||||
sphinx:internal/db/sphinx_impl.go|\
|
||||
sphinx:internal/db/mysql_impl.go|\
|
||||
sqlserver:internal/db/sqlserver_impl.go|\
|
||||
sqlite:internal/db/sqlite_impl.go|\
|
||||
duckdb:internal/db/duckdb_impl.go|\
|
||||
duckdb:internal/db/duckdb_driver_import.go|\
|
||||
duckdb:internal/db/duckdb_platform_supported.go|\
|
||||
duckdb:internal/db/duckdb_platform_unsupported.go|\
|
||||
dameng:internal/db/dameng_impl.go|\
|
||||
dameng:internal/db/dameng_metadata.go|\
|
||||
kingbase:internal/db/kingbase_impl.go|\
|
||||
kingbase:internal/db/kingbase_identifier_utils.go|\
|
||||
highgo:internal/db/highgo_impl.go|\
|
||||
vastbase:internal/db/vastbase_impl.go|\
|
||||
mongodb:internal/db/mongodb_impl.go|\
|
||||
mongodb:internal/db/mongodb_impl_v1.go|\
|
||||
tdengine:internal/db/tdengine_impl.go|\
|
||||
clickhouse:internal/db/clickhouse_impl.go)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
should_include_source_file() {
|
||||
local driver="$1"
|
||||
local identity="$2"
|
||||
if [[ "$identity" == internal/db/* ]]; then
|
||||
should_include_internal_db_file "$driver" "$identity"
|
||||
return
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
target_platform=""
|
||||
driver_csv=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--platform)
|
||||
target_platform="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--drivers)
|
||||
driver_csv="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "未知参数:$1" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! command -v go >/dev/null 2>&1; then
|
||||
echo "未找到 Go,请先安装 Go 并确保 go 在 PATH 中。" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$target_platform" ]]; then
|
||||
target_platform="$(go env GOOS)/$(go env GOARCH)"
|
||||
fi
|
||||
if [[ "$target_platform" != */* ]]; then
|
||||
echo "--platform 参数格式错误,应为 GOOS/GOARCH,例如 darwin/arm64" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
goos="${target_platform%%/*}"
|
||||
goarch="${target_platform##*/}"
|
||||
gomodcache="$(go env GOMODCACHE)"
|
||||
|
||||
declare -a drivers=()
|
||||
if [[ -n "$driver_csv" ]]; then
|
||||
IFS=',' read -r -a raw_drivers <<<"$driver_csv"
|
||||
for item in "${raw_drivers[@]}"; do
|
||||
drivers+=("$(normalize_driver "$item")")
|
||||
done
|
||||
else
|
||||
drivers=("${DEFAULT_DRIVERS[@]}")
|
||||
fi
|
||||
|
||||
fingerprint_driver() {
|
||||
local driver="$1"
|
||||
local build_driver tag cgo_enabled tmp file identity file_hash revision
|
||||
build_driver="$(build_driver_name "$driver")"
|
||||
tag="gonavi_${build_driver}_driver"
|
||||
cgo_enabled=0
|
||||
if [[ "$driver" == "duckdb" ]]; then
|
||||
cgo_enabled=1
|
||||
fi
|
||||
|
||||
tmp="$(mktemp "${TMPDIR:-/tmp}/gonavi-agent-revision.XXXXXX")"
|
||||
{
|
||||
printf 'driver=%s\n' "$driver"
|
||||
printf 'build_tag=%s\n' "$tag"
|
||||
printf 'goos=%s\n' "$goos"
|
||||
printf 'goarch=%s\n' "$goarch"
|
||||
} >"$tmp"
|
||||
|
||||
while IFS= read -r file; do
|
||||
[[ -n "$file" && -f "$file" ]] || continue
|
||||
case "$file" in
|
||||
"$SCRIPT_DIR"/*)
|
||||
identity="${file#$SCRIPT_DIR/}"
|
||||
;;
|
||||
"$gomodcache"/*)
|
||||
identity="gomod/${file#$gomodcache/}"
|
||||
;;
|
||||
*)
|
||||
identity="$file"
|
||||
;;
|
||||
esac
|
||||
if [[ "$identity" == "$OUTPUT_FILE" ]]; then
|
||||
continue
|
||||
fi
|
||||
if ! should_include_source_file "$driver" "$identity"; then
|
||||
continue
|
||||
fi
|
||||
file_hash="$(hash_file "$file")"
|
||||
printf '%s %s\n' "$file_hash" "$identity"
|
||||
done < <(
|
||||
CGO_ENABLED="$cgo_enabled" GOOS="$goos" GOARCH="$goarch" GOTOOLCHAIN=auto \
|
||||
go list -deps \
|
||||
-tags "$tag" \
|
||||
-f '{{if not .Standard}}{{range .GoFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{range .CgoFiles}}{{$.Dir}}/{{.}}{{"\n"}}{{end}}{{end}}' \
|
||||
./cmd/optional-driver-agent | sort -u
|
||||
) >>"$tmp"
|
||||
|
||||
revision="$(hash_file "$tmp" | cut -c1-16)"
|
||||
rm -f "$tmp"
|
||||
printf 'src-%s' "$revision"
|
||||
}
|
||||
|
||||
tmp_output="$(mktemp "${TMPDIR:-/tmp}/gonavi-agent-revisions-go.XXXXXX")"
|
||||
{
|
||||
cat <<'EOF'
|
||||
// Code generated by tools/generate-driver-agent-revisions.sh; DO NOT EDIT.
|
||||
|
||||
package db
|
||||
|
||||
func init() {
|
||||
optionalDriverAgentRevisions = map[string]string{
|
||||
EOF
|
||||
for driver in "${drivers[@]}"; do
|
||||
revision="$(fingerprint_driver "$driver")"
|
||||
printf '\t\t"%s": "%s",\n' "$driver" "$revision"
|
||||
done
|
||||
cat <<'EOF'
|
||||
}
|
||||
}
|
||||
EOF
|
||||
} >"$tmp_output"
|
||||
|
||||
gofmt -w "$tmp_output"
|
||||
|
||||
if [[ -f "$OUTPUT_FILE" ]] && cmp -s "$tmp_output" "$OUTPUT_FILE"; then
|
||||
rm -f "$tmp_output"
|
||||
else
|
||||
mv "$tmp_output" "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
echo "已生成 driver-agent revisions: $OUTPUT_FILE ($goos/$goarch)"
|
||||
Reference in New Issue
Block a user