Files
MyGoNavi/tools/validate-driver-release-assets.test.py
Syngnat 36a80951a0 🐛 fix(ci/driver): 修复驱动发布错配与 dev 驱动下载命中旧资产
- 发布链路新增 driver release 资产自检,校验已发布二进制与 manifest revision/sha256 一致
- dev-build 与 release 工作流在复用已发布驱动前先校验实际资产,发现旧二进制混入时强制全量重建
- driver manifest 新增 sha256 字段,避免仅凭 source commit 与 manifest 一致就误判发布有效
- 驱动变更检测与全量重建判定纳入 release asset 校验脚本变更,确保链路修复提交会触发自愈重建
- 驱动下载优先使用 GitHub release asset API 地址,并对资产接口按 octet-stream 下载,降低 dev-latest 同名资产命中旧缓存的风险
- 保持 DuckDB 无主键编辑修复不回退,并通过 internal/db 与前端相关回归测试
2026-06-05 20:00:27 +08:00

115 lines
4.4 KiB
Python

#!/usr/bin/env python3
import hashlib
import importlib.util
import pathlib
import tempfile
import unittest
MODULE_PATH = pathlib.Path(__file__).with_name("validate-driver-release-assets.py")
SPEC = importlib.util.spec_from_file_location("validate_driver_release_assets", MODULE_PATH)
MODULE = importlib.util.module_from_spec(SPEC)
assert SPEC.loader is not None
SPEC.loader.exec_module(MODULE)
class ValidateDriverReleaseAssetsTests(unittest.TestCase):
def test_infer_asset_path(self):
self.assertEqual(
MODULE.infer_asset_path("clickhouse-driver-agent-darwin-arm64"),
"MacOS/clickhouse-driver-agent-darwin-arm64",
)
self.assertEqual(
MODULE.infer_asset_path("clickhouse-driver-agent-windows-arm64.exe"),
"Windows/clickhouse-driver-agent-windows-arm64.exe",
)
self.assertEqual(MODULE.infer_asset_path("duckdb.dll"), "Windows/duckdb.dll")
self.assertIsNone(MODULE.infer_asset_path("duckdb-driver.zip"))
def test_validate_release_assets_reports_sha_mismatch(self):
release = {
"assets": [
{
"name": "clickhouse-driver-agent-darwin-arm64",
"browser_download_url": "https://example.test/clickhouse-driver-agent-darwin-arm64",
}
]
}
manifest = {
"assets": {
"clickhouse-driver-agent-darwin-arm64": {
"revision": "src-expected",
"sha256": "deadbeef",
}
}
}
with tempfile.TemporaryDirectory(prefix="gonavi-validate-release-assets-") as tmp:
payload_path = pathlib.Path(tmp) / "clickhouse-driver-agent-darwin-arm64"
payload_path.write_bytes(b"test-binary")
def fake_download(url, destination):
destination.write_bytes(payload_path.read_bytes())
original_download = MODULE.download_url
original_probe = MODULE.probe_metadata_revision
try:
MODULE.download_url = fake_download
MODULE.probe_metadata_revision = lambda _path: "src-expected"
mismatches, skipped = MODULE.validate_release_assets(release, manifest)
finally:
MODULE.download_url = original_download
MODULE.probe_metadata_revision = original_probe
self.assertEqual(skipped, [])
self.assertEqual(len(mismatches), 1)
name, field, actual, expected = mismatches[0]
self.assertEqual(name, "clickhouse-driver-agent-darwin-arm64")
self.assertEqual(field, "sha256")
self.assertEqual(actual, hashlib.sha256(b"test-binary").hexdigest())
self.assertEqual(expected, "deadbeef")
def test_validate_release_assets_reports_revision_mismatch(self):
release = {
"assets": [
{
"name": "clickhouse-driver-agent-darwin-arm64",
"browser_download_url": "https://example.test/clickhouse-driver-agent-darwin-arm64",
}
]
}
payload = b"test-binary"
manifest = {
"assets": {
"clickhouse-driver-agent-darwin-arm64": {
"revision": "src-expected",
"sha256": hashlib.sha256(payload).hexdigest(),
}
}
}
with tempfile.TemporaryDirectory(prefix="gonavi-validate-release-assets-") as tmp:
payload_path = pathlib.Path(tmp) / "clickhouse-driver-agent-darwin-arm64"
payload_path.write_bytes(payload)
def fake_download(url, destination):
destination.write_bytes(payload_path.read_bytes())
original_download = MODULE.download_url
original_probe = MODULE.probe_metadata_revision
try:
MODULE.download_url = fake_download
MODULE.probe_metadata_revision = lambda _path: "src-actual"
mismatches, skipped = MODULE.validate_release_assets(release, manifest)
finally:
MODULE.download_url = original_download
MODULE.probe_metadata_revision = original_probe
self.assertEqual(skipped, [])
self.assertEqual(mismatches, [("clickhouse-driver-agent-darwin-arm64", "revision", "src-actual", "src-expected")])
if __name__ == "__main__":
unittest.main()