Files
autoclip/scripts/check_bundle_size.py
Kris K 593cc62bd5 fix: desktop client, CI fixes, and backend (#61)
Squashed merge of fix/problem-fixes-from-main.

- Desktop client (Tauri v2) wiring + packaging
- CI workflow updates (Python 3.11, Rust toolchain, Tauri CLI, WebKit deps)
- Backend test fix (test_missing_api_key respects CI-injected env var)
- build_backend.py: support CI without venv + Windows-safe ASCII output

Desktop build workflows (Linux/Windows/macOS) still failing — tracked in #65.
2026-05-28 15:48:49 +08:00

192 lines
6.9 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
安装包体积检查脚本
用于检查 Tauri 构建产物的体积,确保不超过预设阈值
"""
import argparse
import os
import sys
from pathlib import Path
from typing import Dict, List, Tuple
class Colors:
RED = '\033[0;31m'
GREEN = '\033[0;32m'
YELLOW = '\033[1;33m'
BLUE = '\033[0;34m'
NC = '\033[0m' # No Color
class BundleSizeChecker:
def __init__(self, project_root: Path, max_size_mb: int = 500):
self.project_root = project_root
self.max_size_mb = max_size_mb
self.max_size_bytes = max_size_mb * 1024 * 1024
# Tauri 构建产物路径
self.bundle_paths = [
project_root / "src-tauri" / "target" / "release" / "bundle",
project_root / "dist",
project_root / "build"
]
def log(self, message: str, color: str = Colors.NC):
"""打印带颜色的日志"""
print(f"{color}{message}{Colors.NC}")
def get_file_size(self, file_path: Path) -> int:
"""获取文件大小(字节)"""
try:
return file_path.stat().st_size
except (OSError, FileNotFoundError):
return 0
def get_dir_size(self, dir_path: Path) -> int:
"""获取目录总大小(字节)"""
total_size = 0
try:
for item in dir_path.rglob('*'):
if item.is_file():
total_size += self.get_file_size(item)
except (OSError, FileNotFoundError):
pass
return total_size
def format_size(self, size_bytes: int) -> str:
"""格式化文件大小"""
if size_bytes < 1024:
return f"{size_bytes} B"
elif size_bytes < 1024 * 1024:
return f"{size_bytes / 1024:.1f} KB"
elif size_bytes < 1024 * 1024 * 1024:
return f"{size_bytes / (1024 * 1024):.1f} MB"
else:
return f"{size_bytes / (1024 * 1024 * 1024):.1f} GB"
def find_bundle_files(self) -> List[Tuple[Path, int]]:
"""查找所有构建产物文件"""
bundle_files = []
for bundle_path in self.bundle_paths:
if bundle_path.exists():
if bundle_path.is_file():
size = self.get_file_size(bundle_path)
bundle_files.append((bundle_path, size))
elif bundle_path.is_dir():
# 查找常见的安装包文件
for pattern in ["*.dmg", "*.pkg", "*.deb", "*.rpm", "*.msi", "*.exe", "*.app"]:
for file_path in bundle_path.rglob(pattern):
if file_path.is_file():
size = self.get_file_size(file_path)
bundle_files.append((file_path, size))
return bundle_files
def check_resource_size(self) -> Dict[str, int]:
"""检查资源文件大小"""
resources_path = self.project_root / "src-tauri" / "resources"
resource_sizes = {}
if not resources_path.exists():
return resource_sizes
for item in resources_path.rglob('*'):
if item.is_file():
size = self.get_file_size(item)
relative_path = item.relative_to(resources_path)
resource_sizes[str(relative_path)] = size
return resource_sizes
def run_check(self, verbose: bool = False) -> bool:
"""运行体积检查"""
self.log("🔍 开始检查安装包体积", Colors.YELLOW)
self.log(f"最大允许体积: {self.format_size(self.max_size_bytes)}", Colors.YELLOW)
self.log("")
# 检查构建产物
bundle_files = self.find_bundle_files()
if not bundle_files:
self.log("⚠️ 未找到构建产物文件", Colors.YELLOW)
self.log("请确保已经运行过构建命令", Colors.YELLOW)
return True
total_size = 0
oversized_files = []
self.log("📦 构建产物文件:", Colors.BLUE)
for file_path, size in bundle_files:
total_size += size
size_str = self.format_size(size)
if size > self.max_size_bytes:
oversized_files.append((file_path, size))
self.log(f"{file_path.name}: {size_str} (超过限制)", Colors.RED)
else:
self.log(f"{file_path.name}: {size_str}", Colors.GREEN)
self.log("")
self.log(f"📊 总大小: {self.format_size(total_size)}", Colors.YELLOW)
# 检查资源文件
if verbose:
self.log("")
self.log("📁 资源文件详情:", Colors.BLUE)
resource_sizes = self.check_resource_size()
# 按大小排序
sorted_resources = sorted(resource_sizes.items(), key=lambda x: x[1], reverse=True)
for relative_path, size in sorted_resources:
size_str = self.format_size(size)
self.log(f" {relative_path}: {size_str}")
# 检查结果
if oversized_files:
self.log("")
self.log("❌ 体积检查失败!", Colors.RED)
self.log("以下文件超过体积限制:", Colors.RED)
for file_path, size in oversized_files:
size_str = self.format_size(size)
self.log(f" - {file_path.name}: {size_str}", Colors.RED)
return False
elif total_size > self.max_size_bytes:
self.log("")
self.log("❌ 体积检查失败!", Colors.RED)
self.log(f"总大小 {self.format_size(total_size)} 超过限制 {self.format_size(self.max_size_bytes)}", Colors.RED)
return False
else:
self.log("")
self.log("✅ 体积检查通过!", Colors.GREEN)
return True
def main():
parser = argparse.ArgumentParser(description='安装包体积检查脚本')
parser.add_argument('-m', '--max-size', type=int, default=500, help='最大允许体积MB默认: 500')
parser.add_argument('-v', '--verbose', action='store_true', help='详细输出')
parser.add_argument('--project-root', type=str, help='项目根目录路径')
args = parser.parse_args()
# 确定项目根目录
if args.project_root:
project_root = Path(args.project_root)
else:
# 从脚本位置推断项目根目录
script_dir = Path(__file__).parent
project_root = script_dir.parent
if not project_root.exists():
print(f"错误: 项目根目录不存在: {project_root}")
sys.exit(1)
# 创建检查器并运行检查
checker = BundleSizeChecker(project_root, args.max_size)
success = checker.run_check(args.verbose)
sys.exit(0 if success else 1)
if __name__ == '__main__':
main()