feat(release): 补齐 Linux arm64 构建与驱动发布链路

- 增加 dev/release 工作流 Linux arm64 构建矩阵与驱动分流
- 补齐在线更新资产识别及 driver release manifest/asset 校验
- 兼容 Windows 本地 bash/python 解析并补充对应测试
This commit is contained in:
Syngnat
2026-07-04 10:15:13 +08:00
parent b388b08226
commit d7e15f5eb0
12 changed files with 228 additions and 20 deletions

View File

@@ -73,6 +73,7 @@ jobs:
drivers_windows_amd64: ${{ steps.detect.outputs.drivers_windows_amd64 }}
drivers_windows_arm64: ${{ steps.detect.outputs.drivers_windows_arm64 }}
drivers_linux_amd64: ${{ steps.detect.outputs.drivers_linux_amd64 }}
drivers_linux_arm64: ${{ steps.detect.outputs.drivers_linux_arm64 }}
has_changes: ${{ steps.detect.outputs.has_changes }}
release_source: ${{ steps.detect.outputs.release_source }}
compare_base: ${{ steps.detect.outputs.compare_base }}
@@ -167,6 +168,7 @@ jobs:
windows/amd64) echo "windows_amd64" ;;
windows/arm64) echo "windows_arm64" ;;
linux/amd64) echo "linux_amd64" ;;
linux/arm64) echo "linux_arm64" ;;
*)
echo "unknown platform: $1" >&2
return 1
@@ -204,7 +206,7 @@ jobs:
PLATFORM_DIFF_FAILED=false
if [[ "$BASE_REF" != "all" && "$FORCE_GLOBAL_DRIVER_BUILDS" != "true" ]]; then
REVISION_DRIVERS=""
for PLATFORM in darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64; do
for PLATFORM in darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64 linux/arm64; do
PLATFORM_KEY="$(platform_output_key "$PLATFORM")"
DIFF_ARGS=(bash ./tools/diff-driver-agent-revisions.sh --base "$BASE_REF" --head "$GITHUB_SHA" --platform "$PLATFORM")
if [[ -n "$DRIVERS" ]]; then
@@ -228,12 +230,12 @@ jobs:
fi
if [[ "$BASE_REF" == "all" || "$FORCE_GLOBAL_DRIVER_BUILDS" == "true" || "$PLATFORM_DIFF_FAILED" == "true" ]]; then
PLATFORM_OUTPUTS=()
for PLATFORM in darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64; do
for PLATFORM in darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64 linux/arm64; do
PLATFORM_KEY="$(platform_output_key "$PLATFORM")"
PLATFORM_OUTPUTS+=("drivers_${PLATFORM_KEY}=${DRIVERS}")
done
elif [[ ${#PLATFORM_OUTPUTS[@]} -eq 0 ]]; then
for PLATFORM in darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64; do
for PLATFORM in darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64 linux/arm64; do
PLATFORM_KEY="$(platform_output_key "$PLATFORM")"
PLATFORM_OUTPUTS+=("drivers_${PLATFORM_KEY}=")
done
@@ -312,6 +314,15 @@ jobs:
artifact_suffix: ""
build_optional_agents: true
linux_webkit: "4.0"
- os: ubuntu-22.04-arm
platform: linux/arm64
os_name: Linux
arch_name: Arm64
build_name: gonavi-build-linux-arm64
wails_tags: ""
artifact_suffix: ""
build_optional_agents: true
linux_webkit: "4.0"
- os: ubuntu-24.04
platform: linux/amd64
os_name: Linux
@@ -397,6 +408,12 @@ jobs:
sudo apt-get install -y libfuse2 || sudo apt-get install -y libfuse2t64 || true
if [ "${{ matrix.arch_name }}" != "Amd64" ]; then
echo "⚠️ Linux arm64 暂不生成 AppImage仅产出 tar.gz"
touch /tmp/skip-appimage
exit 0
fi
LINUXDEPLOY_URL="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
PLUGIN_URL="https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/releases/download/continuous/linuxdeploy-plugin-gtk-x86_64.AppImage"
@@ -554,6 +571,9 @@ jobs:
linux/amd64)
DRIVERS='${{ needs.driver_agents.outputs.drivers_linux_amd64 }}'
;;
linux/arm64)
DRIVERS='${{ needs.driver_agents.outputs.drivers_linux_arm64 }}'
;;
*)
echo "unsupported platform: ${{ matrix.platform }}" >&2
exit 1

View File

@@ -177,7 +177,7 @@ jobs:
DRIVERS="$(bash ./tools/detect-changed-driver-agents.sh --base "$BASE_REF" --head "$GITHUB_SHA")"
if [[ "$BASE_REF" != "all" ]]; then
REVISION_DRIVERS=""
for PLATFORM in darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64; do
for PLATFORM in darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64 linux/arm64; do
PLATFORM_DRIVERS="$(bash ./tools/diff-driver-agent-revisions.sh --base "$BASE_REF" --head "$GITHUB_SHA" --platform "$PLATFORM")" || {
echo "⚠️ 平台 revision 差异对比失败(${PLATFORM}),保守回退为全量驱动重建"
DRIVERS="$(bash ./tools/detect-changed-driver-agents.sh --base all --head "$GITHUB_SHA")"
@@ -263,6 +263,15 @@ jobs:
artifact_suffix: ""
build_optional_agents: true
linux_webkit: "4.0"
- os: ubuntu-22.04-arm
platform: linux/arm64
os_name: Linux
arch_name: Arm64
build_name: gonavi-build-linux-arm64
wails_tags: ""
artifact_suffix: ""
build_optional_agents: true
linux_webkit: "4.0"
# Debian 13 (trixie) 默认仓库已切到 WebKitGTK 4.1:单独提供 4.1 变体产物
- os: ubuntu-24.04
platform: linux/amd64
@@ -354,6 +363,12 @@ jobs:
# AppImage 运行/打包可能需要 FUSE2。不同发行版/版本包名不同,做兼容兜底。
sudo apt-get install -y libfuse2 || sudo apt-get install -y libfuse2t64 || true
if [ "${{ matrix.arch_name }}" != "Amd64" ]; then
echo "⚠️ Linux arm64 暂不生成 AppImage仅产出 tar.gz"
touch /tmp/skip-appimage
exit 0
fi
# Download linuxdeploy tools for AppImage packaging
LINUXDEPLOY_URL="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
PLUGIN_URL="https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/releases/download/continuous/linuxdeploy-plugin-gtk-x86_64.AppImage"

View File

@@ -566,6 +566,9 @@ func expectedAssetNameForExecutable(goos, goarch, version, executablePath string
if goarch == "amd64" {
return fmt.Sprintf("GoNavi-%s-Linux-Amd64%s.tar.gz", version, resolveLinuxReleaseArtifactSuffix(executablePath)), nil
}
if goarch == "arm64" {
return fmt.Sprintf("GoNavi-%s-Linux-Arm64%s.tar.gz", version, resolveLinuxReleaseArtifactSuffix(executablePath)), nil
}
}
return "", localizedUpdateError{
key: "app.update.backend.error.online_update_unsupported",

View File

@@ -190,6 +190,23 @@ func TestExpectedAssetNameForExecutableUsesLinuxWebKit41Suffix(t *testing.T) {
}
}
func TestExpectedAssetNameForExecutableSupportsLinuxArm64(t *testing.T) {
assetName, err := expectedAssetNameForExecutable(
"linux",
"arm64",
"v0.6.5",
"/opt/GoNavi/gonavi-build-linux-arm64",
)
if err != nil {
t.Fatalf("expectedAssetNameForExecutable returned error: %v", err)
}
want := "GoNavi-0.6.5-Linux-Arm64.tar.gz"
if assetName != want {
t.Fatalf("unexpected linux arm64 asset name: got %q want %q", assetName, want)
}
}
func TestBuildLinuxScriptPrefersTargetExecutableBasename(t *testing.T) {
script := buildLinuxScript(
"/tmp/GoNavi-0.6.5-Linux-Amd64-WebKit41.tar.gz",

View File

@@ -48,6 +48,7 @@ def required_assets():
("MacOS", f"{driver}-driver-agent-darwin-amd64"),
("MacOS", f"{driver}-driver-agent-darwin-arm64"),
("Linux", f"{driver}-driver-agent-linux-amd64"),
("Linux", f"{driver}-driver-agent-linux-arm64"),
]
)
if driver == "duckdb":

View File

@@ -8,7 +8,7 @@ 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 gaussdb iris mongodb tdengine iotdb clickhouse elasticsearch)
TARGET_PLATFORMS=(darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64)
TARGET_PLATFORMS=(darwin/amd64 darwin/arm64 windows/amd64 windows/arm64 linux/amd64 linux/arm64)
usage() {
cat <<'EOF'
@@ -627,8 +627,9 @@ 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
if [[ "$matched_platforms" == *"|linux/amd64|"* || "$matched_platforms" == *"|linux/arm64|"* ]]; then
add_analysis_platform "linux/amd64"
add_analysis_platform "linux/arm64"
continue
fi
for platform in "${TARGET_PLATFORMS[@]}"; do

View File

@@ -4,6 +4,8 @@ import argparse
import hashlib
import json
import os
import shlex
import shutil
import subprocess
import sys
import tempfile
@@ -22,16 +24,19 @@ def infer_driver_and_platform(file_name: str):
("-driver-agent-v1-darwin-amd64", "darwin/amd64"),
("-driver-agent-v1-darwin-arm64", "darwin/arm64"),
("-driver-agent-v1-linux-amd64", "linux/amd64"),
("-driver-agent-v1-linux-arm64", "linux/arm64"),
("-driver-agent-v1-windows-amd64.exe", "windows/amd64"),
("-driver-agent-v1-windows-arm64.exe", "windows/arm64"),
("-driver-agent-v2-darwin-amd64", "darwin/amd64"),
("-driver-agent-v2-darwin-arm64", "darwin/arm64"),
("-driver-agent-v2-linux-amd64", "linux/amd64"),
("-driver-agent-v2-linux-arm64", "linux/arm64"),
("-driver-agent-v2-windows-amd64.exe", "windows/amd64"),
("-driver-agent-v2-windows-arm64.exe", "windows/arm64"),
("-driver-agent-darwin-amd64", "darwin/amd64"),
("-driver-agent-darwin-arm64", "darwin/arm64"),
("-driver-agent-linux-amd64", "linux/amd64"),
("-driver-agent-linux-arm64", "linux/arm64"),
("-driver-agent-windows-amd64.exe", "windows/amd64"),
("-driver-agent-windows-arm64.exe", "windows/arm64"),
]
@@ -53,6 +58,49 @@ def repo_root():
return Path(__file__).resolve().parent.parent
def resolve_bash_executable():
env_value = str(os.environ.get("BASH") or "").strip()
if env_value:
candidate = Path(env_value)
if candidate.is_file():
return str(candidate)
resolved = shutil.which("bash")
if resolved:
return resolved
if os.name == "nt":
for candidate in (
Path(r"C:\msys64\usr\bin\bash.exe"),
Path(r"C:\Program Files\Git\bin\bash.exe"),
Path(r"C:\Program Files\Git\usr\bin\bash.exe"),
Path(r"D:\Work\DevTools\Git\Git\bin\bash.exe"),
Path(r"D:\Work\DevTools\Git\Git\usr\bin\bash.exe"),
):
if candidate.is_file():
return str(candidate)
raise FileNotFoundError("bash executable not found; set BASH or add bash to PATH")
def to_bash_path(path):
text = str(path)
if os.name == "nt":
text = text.replace("\\", "/")
if len(text) >= 2 and text[1] == ":":
return f"/{text[0].lower()}{text[2:]}"
return text
def run_bash_command(bash_executable: str, cwd: Path, command: list[str], **kwargs):
env = dict(kwargs.pop("env", os.environ.copy()))
if os.name == "nt":
env.setdefault("MSYS2_PATH_TYPE", "inherit")
command_text = " ".join(shlex.quote(str(part)) for part in command)
bash_command = f"cd {shlex.quote(to_bash_path(cwd))} && {command_text}"
return subprocess.run([bash_executable, "-lc", bash_command], env=env, **kwargs)
def resolve_head_commit(root: Path):
proc = subprocess.run(
["git", "rev-parse", "HEAD"],
@@ -83,6 +131,7 @@ def generate_platform_revisions(root: Path, drivers_by_platform):
if not drivers_by_platform:
return {}
bash_executable = resolve_bash_executable()
with tempfile.TemporaryDirectory(prefix="gonavi-driver-release-manifest-") as tmp:
worktree = Path(tmp) / "worktree"
subprocess.run(
@@ -97,12 +146,10 @@ def generate_platform_revisions(root: Path, drivers_by_platform):
result = {}
for platform in sorted(drivers_by_platform):
drivers = sorted({normalize_driver(driver) for driver in drivers_by_platform[platform] if normalize_driver(driver)})
command = ["bash", "./tools/generate-driver-agent-revisions.sh", "--platform", platform]
if drivers:
command.extend(["--drivers", ",".join(drivers)])
subprocess.run(
command,
cwd=worktree,
run_bash_command(
bash_executable,
worktree,
["./tools/generate-driver-agent-revisions.sh", "--platform", platform, *([] if not drivers else ["--drivers", ",".join(drivers)])],
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
text=True,

View File

@@ -2,8 +2,11 @@
import json
import os
import shlex
import shutil
import stat
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
@@ -13,6 +16,49 @@ ROOT = Path(__file__).resolve().parent.parent
SCRIPT = ROOT / "tools" / "generate-driver-release-manifest.py"
def resolve_bash_executable():
env_value = str(os.environ.get("BASH") or "").strip()
if env_value:
candidate = Path(env_value)
if candidate.is_file():
return str(candidate)
resolved = shutil.which("bash")
if resolved:
return resolved
if os.name == "nt":
for candidate in (
Path(r"C:\msys64\usr\bin\bash.exe"),
Path(r"C:\Program Files\Git\bin\bash.exe"),
Path(r"C:\Program Files\Git\usr\bin\bash.exe"),
Path(r"D:\Work\DevTools\Git\Git\bin\bash.exe"),
Path(r"D:\Work\DevTools\Git\Git\usr\bin\bash.exe"),
):
if candidate.is_file():
return str(candidate)
raise FileNotFoundError("bash executable not found; set BASH or add bash to PATH")
def to_bash_path(path):
text = str(path)
if os.name == "nt":
text = text.replace("\\", "/")
if len(text) >= 2 and text[1] == ":":
return f"/{text[0].lower()}{text[2:]}"
return text
def run_bash_command(bash_executable: str, cwd: Path, command: list[str], **kwargs):
env = dict(kwargs.pop("env", os.environ.copy()))
if os.name == "nt":
env.setdefault("MSYS2_PATH_TYPE", "inherit")
command_text = " ".join(shlex.quote(str(part)) for part in command)
bash_command = f"cd {shlex.quote(to_bash_path(cwd))} && {command_text}"
return subprocess.run([bash_executable, "-lc", bash_command], env=env, **kwargs)
def expected_revision(revision_file: Path, driver: str):
for line in revision_file.read_text(encoding="utf-8").splitlines():
if f'"{driver}"' not in line:
@@ -25,6 +71,7 @@ def expected_revision(revision_file: Path, driver: str):
class GenerateDriverReleaseManifestTest(unittest.TestCase):
def _generate_revision_file(self, platform: str, drivers: str = "clickhouse"):
bash_executable = resolve_bash_executable()
worktree = Path(tempfile.mkdtemp(prefix="gonavi-release-manifest-worktree-"))
subprocess.run(
["git", "worktree", "add", "--detach", str(worktree), "HEAD"],
@@ -42,9 +89,10 @@ class GenerateDriverReleaseManifestTest(unittest.TestCase):
check=False,
)
)
subprocess.run(
["bash", "./tools/generate-driver-agent-revisions.sh", "--platform", platform, "--drivers", drivers],
cwd=worktree,
run_bash_command(
bash_executable,
worktree,
["./tools/generate-driver-agent-revisions.sh", "--platform", platform, "--drivers", drivers],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=True,
@@ -62,6 +110,7 @@ class GenerateDriverReleaseManifestTest(unittest.TestCase):
fixtures = {
assets_dir / "MacOS" / "clickhouse-driver-agent-darwin-arm64": b"darwin-binary",
assets_dir / "Linux" / "clickhouse-driver-agent-linux-amd64": b"linux-binary",
assets_dir / "Linux" / "clickhouse-driver-agent-linux-arm64": b"linux-arm64-binary",
assets_dir / "Windows" / "clickhouse-driver-agent-windows-amd64.exe": b"MZfake-binary",
assets_dir / "Windows" / "mongodb-driver-agent-v1-windows-amd64.exe": b"MZfake-mongodb-v1",
assets_dir / "Windows" / "mongodb-driver-agent-v2-windows-amd64.exe": b"MZfake-mongodb-v2",
@@ -72,7 +121,7 @@ class GenerateDriverReleaseManifestTest(unittest.TestCase):
output = tmpdir / "manifest.json"
proc = subprocess.run(
["python3", str(SCRIPT), "--assets-dir", str(assets_dir), "--output", str(output)],
[sys.executable, str(SCRIPT), "--assets-dir", str(assets_dir), "--output", str(output)],
cwd=ROOT,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
@@ -85,6 +134,7 @@ class GenerateDriverReleaseManifestTest(unittest.TestCase):
assets = manifest["assets"]
darwin_revision_file = self._generate_revision_file("darwin/arm64")
linux_revision_file = self._generate_revision_file("linux/amd64")
linux_arm64_revision_file = self._generate_revision_file("linux/arm64")
windows_revision_file = self._generate_revision_file("windows/amd64", "clickhouse,mongodb")
self.assertEqual(
assets["clickhouse-driver-agent-darwin-arm64"]["revision"],
@@ -94,6 +144,10 @@ class GenerateDriverReleaseManifestTest(unittest.TestCase):
assets["clickhouse-driver-agent-linux-amd64"]["revision"],
expected_revision(linux_revision_file, "clickhouse"),
)
self.assertEqual(
assets["clickhouse-driver-agent-linux-arm64"]["revision"],
expected_revision(linux_arm64_revision_file, "clickhouse"),
)
self.assertEqual(
assets["clickhouse-driver-agent-windows-amd64.exe"]["revision"],
expected_revision(windows_revision_file, "clickhouse"),

View File

@@ -100,8 +100,11 @@ def infer_asset_path(name: str):
return f"MacOS/{trimmed}"
if (
trimmed.endswith("-driver-agent-linux-amd64")
or trimmed.endswith("-driver-agent-linux-arm64")
or trimmed.endswith("-driver-agent-v1-linux-amd64")
or trimmed.endswith("-driver-agent-v1-linux-arm64")
or trimmed.endswith("-driver-agent-v2-linux-amd64")
or trimmed.endswith("-driver-agent-v2-linux-arm64")
):
return f"Linux/{trimmed}"
return None

View File

@@ -32,6 +32,10 @@ class ValidateDriverReleaseAssetsTests(unittest.TestCase):
MODULE.infer_asset_path("mongodb-driver-agent-v2-darwin-arm64"),
"MacOS/mongodb-driver-agent-v2-darwin-arm64",
)
self.assertEqual(
MODULE.infer_asset_path("clickhouse-driver-agent-linux-arm64"),
"Linux/clickhouse-driver-agent-linux-arm64",
)
self.assertEqual(MODULE.infer_asset_path("duckdb.dll"), "Windows/duckdb.dll")
self.assertIsNone(MODULE.infer_asset_path("duckdb-driver.zip"))

View File

@@ -51,6 +51,23 @@ if [[ ! -f "$manifest_path" ]]; then
exit 1
fi
resolve_python_bin() {
local candidate
for candidate in python3 python; do
if command -v "$candidate" >/dev/null 2>&1 && "$candidate" -V >/dev/null 2>&1; then
printf '%s\n' "$candidate"
return 0
fi
done
return 1
}
PYTHON_BIN="$(resolve_python_bin || true)"
if [[ -z "$PYTHON_BIN" ]]; then
echo "未找到 Python请先安装 python3 或 python 并确保其在 PATH 中。" >&2
exit 1
fi
if ! git rev-parse --verify "${source_commit}^{commit}" >/dev/null 2>&1; then
echo "无法解析源码提交:$source_commit" >&2
exit 1
@@ -87,7 +104,7 @@ trap cleanup EXIT
git worktree add --detach "$worktree" "${source_commit}^{commit}" >/dev/null
python3 - "$manifest_path" "$worktree" <<'PY'
"$PYTHON_BIN" - "$manifest_path" "$worktree" <<'PY'
import json
import subprocess
import sys

View File

@@ -17,6 +17,22 @@ cleanup() {
trap cleanup EXIT
manifest_path="$tmpdir/manifest.json"
resolve_python_bin() {
local candidate
for candidate in python3 python; do
if command -v "$candidate" >/dev/null 2>&1 && "$candidate" -V >/dev/null 2>&1; then
printf '%s\n' "$candidate"
return 0
fi
done
return 1
}
PYTHON_BIN="$(resolve_python_bin || true)"
if [[ -z "$PYTHON_BIN" ]]; then
echo "skip: validate-driver-release-manifest.test.sh requires python3 or python" >&2
exit 0
fi
generate_revision() {
local platform="$1"
@@ -59,6 +75,13 @@ cat >"$manifest_path" <<'EOF'
"revision": "__CLICKHOUSE_LINUX_AMD64__",
"size": 1
},
"clickhouse-driver-agent-linux-arm64": {
"driver": "clickhouse",
"driverType": "clickhouse",
"platform": "linux/arm64",
"revision": "__CLICKHOUSE_LINUX_ARM64__",
"size": 1
},
"clickhouse-driver-agent-windows-amd64.exe": {
"driver": "clickhouse",
"driverType": "clickhouse",
@@ -79,10 +102,11 @@ EOF
clickhouse_darwin_revision="$(generate_revision darwin/arm64 clickhouse)"
clickhouse_linux_revision="$(generate_revision linux/amd64 clickhouse)"
clickhouse_linux_arm64_revision="$(generate_revision linux/arm64 clickhouse)"
clickhouse_windows_revision="$(generate_revision windows/amd64 clickhouse)"
mariadb_darwin_revision="$(generate_revision darwin/arm64 mariadb)"
python3 - "$manifest_path" "$clickhouse_darwin_revision" "$clickhouse_linux_revision" "$clickhouse_windows_revision" "$mariadb_darwin_revision" <<'PY'
"$PYTHON_BIN" - "$manifest_path" "$clickhouse_darwin_revision" "$clickhouse_linux_revision" "$clickhouse_linux_arm64_revision" "$clickhouse_windows_revision" "$mariadb_darwin_revision" <<'PY'
import json
import sys
from pathlib import Path
@@ -90,11 +114,13 @@ from pathlib import Path
path = Path(sys.argv[1])
clickhouse_darwin = sys.argv[2]
clickhouse_linux = sys.argv[3]
clickhouse_windows = sys.argv[4]
mariadb = sys.argv[5]
clickhouse_linux_arm64 = sys.argv[4]
clickhouse_windows = sys.argv[5]
mariadb = sys.argv[6]
data = json.loads(path.read_text(encoding="utf-8"))
data["assets"]["clickhouse-driver-agent-darwin-arm64"]["revision"] = clickhouse_darwin
data["assets"]["clickhouse-driver-agent-linux-amd64"]["revision"] = clickhouse_linux
data["assets"]["clickhouse-driver-agent-linux-arm64"]["revision"] = clickhouse_linux_arm64
data["assets"]["clickhouse-driver-agent-windows-amd64.exe"]["revision"] = clickhouse_windows
data["assets"]["mariadb-driver-agent-darwin-arm64"]["revision"] = mariadb
path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")