Files
MyGoNavi/tools/package-driver-release-assets.test.py
Syngnat 84d6007be9 ️ perf(driver/release): 优化驱动镜像下载与发布链路
- 将各平台驱动拆分为独立 ZIP,并为 DuckDB 同包携带运行库
- 仅生成 ZIP 下载候选,按 Gatewaysentry 与 GitHub 短测速结果调整优先级
- 扩展发布索引的归档摘要与条目元数据,强化跨平台资产校验
- 禁止裸驱动与 CI 总包进入 VPS 镜像,并校验载荷摘要和索引一致性
- 显式控制驱动镜像发布,自动清理失败暂存、过期目录和旧版本
2026-07-23 16:10:08 +08:00

200 lines
8.4 KiB
Python

#!/usr/bin/env python3
import hashlib
import json
import subprocess
import tempfile
import unittest
import zipfile
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
SCRIPT = ROOT / "tools" / "package-driver-release-assets.py"
class PackageDriverReleaseAssetsTest(unittest.TestCase):
def test_packages_ci_bundle_and_individual_archives_without_raw_assets(self):
with tempfile.TemporaryDirectory(prefix="gonavi-driver-assets-test-") as tmp:
tmpdir = Path(tmp)
drivers_dir = tmpdir / "drivers"
output_dir = tmpdir / "driver-release-assets"
(drivers_dir / "Windows").mkdir(parents=True)
(drivers_dir / "MacOS").mkdir(parents=True)
windows_asset = drivers_dir / "Windows" / "clickhouse-driver-agent-windows-amd64.exe"
darwin_asset = drivers_dir / "MacOS" / "clickhouse-driver-agent-darwin-arm64"
windows_asset.write_bytes(b"windows-asset")
darwin_asset.write_bytes(b"darwin-asset")
proc = subprocess.run(
["python3", str(SCRIPT), str(drivers_dir), str(output_dir)],
cwd=ROOT,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True,
)
self.assertIn("created GoNavi-DriverAgents.zip", proc.stdout)
self.assertTrue((output_dir / "GoNavi-DriverAgents.zip").is_file())
windows_archive = output_dir / "clickhouse-driver-agent-windows-amd64.zip"
darwin_archive = output_dir / "clickhouse-driver-agent-darwin-arm64.zip"
self.assertTrue(windows_archive.is_file())
self.assertTrue(darwin_archive.is_file())
self.assertFalse((output_dir / windows_asset.name).exists())
self.assertFalse((output_dir / darwin_asset.name).exists())
self.assertEqual((output_dir / "LICENSE").read_bytes(), (ROOT / "LICENSE").read_bytes())
self.assertEqual((output_dir / "NOTICE").read_bytes(), (ROOT / "NOTICE").read_bytes())
index = json.loads((output_dir / "GoNavi-DriverAgents-Index.json").read_text(encoding="utf-8"))
self.assertEqual(set(index), {"assets", "assetSha256", "entries"})
self.assertEqual(
index["assets"],
{
windows_archive.name: windows_archive.stat().st_size,
darwin_archive.name: darwin_archive.stat().st_size,
},
)
self.assertEqual(
index["assetSha256"],
{
windows_archive.name: hashlib.sha256(windows_archive.read_bytes()).hexdigest(),
darwin_archive.name: hashlib.sha256(darwin_archive.read_bytes()).hexdigest(),
},
)
self.assertEqual(
index["entries"],
{
windows_asset.name: {
"archive": windows_archive.name,
"path": "Windows/clickhouse-driver-agent-windows-amd64.exe",
"size": len(b"windows-asset"),
"sha256": hashlib.sha256(b"windows-asset").hexdigest(),
},
darwin_asset.name: {
"archive": darwin_archive.name,
"path": "MacOS/clickhouse-driver-agent-darwin-arm64",
"size": len(b"darwin-asset"),
"sha256": hashlib.sha256(b"darwin-asset").hexdigest(),
},
},
)
self.assertNotIn("GoNavi-DriverAgents.zip", index["assets"])
self.assertNotIn("GoNavi-DriverAgents.zip", index["assetSha256"])
with zipfile.ZipFile(windows_archive) as zf:
self.assertEqual(
sorted(zf.namelist()),
[
"LICENSE",
"NOTICE",
"Windows/clickhouse-driver-agent-windows-amd64.exe",
],
)
self.assertEqual(
zf.read("Windows/clickhouse-driver-agent-windows-amd64.exe"),
b"windows-asset",
)
with zipfile.ZipFile(darwin_archive) as zf:
self.assertEqual(
sorted(zf.namelist()),
[
"LICENSE",
"MacOS/clickhouse-driver-agent-darwin-arm64",
"NOTICE",
],
)
self.assertEqual(
zf.read("MacOS/clickhouse-driver-agent-darwin-arm64"),
b"darwin-asset",
)
with zipfile.ZipFile(output_dir / "GoNavi-DriverAgents.zip") as zf:
self.assertEqual(
sorted(zf.namelist()),
[
"LICENSE",
"MacOS/clickhouse-driver-agent-darwin-arm64",
"NOTICE",
"Windows/clickhouse-driver-agent-windows-amd64.exe",
],
)
self.assertEqual(zf.read("LICENSE"), (ROOT / "LICENSE").read_bytes())
self.assertEqual(zf.read("NOTICE"), (ROOT / "NOTICE").read_bytes())
def test_rebuilds_duckdb_windows_archive_with_agent_and_library(self):
with tempfile.TemporaryDirectory(prefix="gonavi-driver-assets-test-") as tmp:
tmpdir = Path(tmp)
drivers_dir = tmpdir / "drivers"
output_dir = tmpdir / "driver-release-assets"
windows_dir = drivers_dir / "Windows"
windows_dir.mkdir(parents=True)
agent = windows_dir / "duckdb-driver-agent-windows-amd64.exe"
library = windows_dir / "duckdb.dll"
agent.write_bytes(b"duckdb-agent")
library.write_bytes(b"duckdb-library")
(windows_dir / "duckdb-driver.zip").write_bytes(b"stale-source-package")
subprocess.run(
["python3", str(SCRIPT), str(drivers_dir), str(output_dir)],
cwd=ROOT,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True,
)
archive = output_dir / "duckdb-driver-agent-windows-amd64.zip"
self.assertTrue(archive.is_file())
self.assertFalse((output_dir / agent.name).exists())
self.assertFalse((output_dir / library.name).exists())
index = json.loads((output_dir / "GoNavi-DriverAgents-Index.json").read_text(encoding="utf-8"))
self.assertEqual(index["assets"], {archive.name: archive.stat().st_size})
self.assertEqual(
index["assetSha256"],
{archive.name: hashlib.sha256(archive.read_bytes()).hexdigest()},
)
self.assertEqual(
index["entries"],
{
agent.name: {
"archive": archive.name,
"path": "Windows/duckdb-driver-agent-windows-amd64.exe",
"size": len(b"duckdb-agent"),
"sha256": hashlib.sha256(b"duckdb-agent").hexdigest(),
},
library.name: {
"archive": archive.name,
"path": "Windows/duckdb.dll",
"size": len(b"duckdb-library"),
"sha256": hashlib.sha256(b"duckdb-library").hexdigest(),
},
},
)
with zipfile.ZipFile(archive) as zf:
self.assertEqual(
sorted(zf.namelist()),
[
"LICENSE",
"NOTICE",
"Windows/duckdb-driver-agent-windows-amd64.exe",
"Windows/duckdb.dll",
],
)
self.assertEqual(
zf.read("Windows/duckdb-driver-agent-windows-amd64.exe"),
b"duckdb-agent",
)
self.assertEqual(zf.read("Windows/duckdb.dll"), b"duckdb-library")
with zipfile.ZipFile(output_dir / "GoNavi-DriverAgents.zip") as zf:
self.assertNotIn("Windows/duckdb-driver.zip", zf.namelist())
if __name__ == "__main__":
unittest.main()