#!/usr/bin/env python3 """Create one self-contained browser OTA package on the development computer.""" from __future__ import annotations import argparse from datetime import datetime, timezone import hashlib from pathlib import Path import sys SOURCE_ROOT = Path(__file__).resolve().parents[1] if str(SOURCE_ROOT) not in sys.path: sys.path.insert(0, str(SOURCE_ROOT)) from app.ota.package import build_package from app.ota.versioning import read_software_version from app.ota.policy import read_policy def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--notes", required=True, help="short release description") parser.add_argument("--output-root", type=Path) args = parser.parse_args() source_root = Path(__file__).resolve().parents[1] project_root = source_root.parent wheelhouse = project_root / "发布更新相关" / "其他依赖" / "aarch64-py311" frpc_bundle = project_root / "发布更新相关" / "其他依赖" / "frp" / "0.71.0" / "linux-arm64" version = read_software_version(source_root) policy = read_policy(source_root) if policy["checkpoints"] and version < type(version).parse(policy["checkpoints"][-1]["version"]): parser.error("源码包含未发布的软件依赖;请使用 export_release.py ota --version 导出安装节点") if version.patch != 0: frpc_bundle = None output_root = (args.output_root or project_root / "发布更新相关" / "OTA数据包").resolve() version_dir = output_root / str(version) if version_dir.exists(): parser.error(f"version output already exists and will not be overwritten: {version_dir}") version_dir.mkdir(parents=True) package_path = version_dir / f"matrix-screen-controller-{version}.ota" created = datetime.now(timezone.utc) try: info = build_package( source_root, wheelhouse, package_path, version=version, release_notes=args.notes, created_at=created, system_dependencies=frpc_bundle, ) package_sha = hashlib.sha256(package_path.read_bytes()).hexdigest() readme = ( f"# 奇妙小屏幕控制器 OTA {version}\n\n" f"- 软件版本:`{version}`\n" f"- 打包时间:`{info.created_at}`\n" f"- 更新说明:{args.notes.strip()}\n" f"- 更新包:`{package_path.name}`\n" f"- 文件大小:`{package_path.stat().st_size}` bytes\n" f"- 文件 SHA-256:`{package_sha}`\n" f"- 载荷 SHA-256:`{info.payload_sha256}`\n\n" "通过设备网页的“系统设置 → 软件更新”选择 `.ota` 文件。" "本包是离线全量包,不使用服务器下载、增量、加密或签名。\n" ) (version_dir / "README.md").write_text(readme, encoding="utf-8", newline="\n") except BaseException: package_path.unlink(missing_ok=True) try: version_dir.rmdir() except OSError: pass raise print(version_dir) return 0 if __name__ == "__main__": raise SystemExit(main())