feat: 版本号管理、构建日志持久化、App_Store 构建号自动递增
- 新增版本号配置 API(GET/PUT /api/config/versions)和前端管理界面
- 构建日志收集与保存:任务完成/取消/失败时写入 build.log
- 新增任务日志查询接口 GET /api/tasks/{task_id}/log
- App_Store 打包时自动递增 Build_Ver 第四位版本号
- 从 Provisioning Profile 自动提取 TEAM_ID 和 PROVISIONING_NAME
- 前端完成后支持查看完整构建日志
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import asyncio
|
||||
import json
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict, AsyncGenerator
|
||||
|
||||
|
||||
@@ -11,24 +12,30 @@ class LogStreamer:
|
||||
def __init__(self):
|
||||
self._queues: Dict[str, asyncio.Queue] = {}
|
||||
self._subscribers: Dict[str, list] = {}
|
||||
self._log_lines: Dict[str, list] = {}
|
||||
|
||||
def create_queue(self, task_id: str) -> asyncio.Queue:
|
||||
"""创建任务的日志队列"""
|
||||
queue = asyncio.Queue(maxsize=1000)
|
||||
self._queues[task_id] = queue
|
||||
self._log_lines[task_id] = []
|
||||
return queue
|
||||
|
||||
async def emit(self, task_id: str, message: str, level: str = "info"):
|
||||
"""发送日志消息"""
|
||||
if task_id not in self._queues:
|
||||
return
|
||||
|
||||
log_entry = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"level": level,
|
||||
"message": message,
|
||||
}
|
||||
|
||||
# 收集日志
|
||||
if task_id in self._log_lines:
|
||||
self._log_lines[task_id].append(log_entry)
|
||||
|
||||
if task_id not in self._queues:
|
||||
return
|
||||
|
||||
try:
|
||||
self._queues[task_id].put_nowait(log_entry)
|
||||
except asyncio.QueueFull:
|
||||
@@ -81,6 +88,27 @@ class LogStreamer:
|
||||
"""清理任务日志队列"""
|
||||
self._queues.pop(task_id, None)
|
||||
|
||||
def save_log(self, task_id: str, build_dir: Path):
|
||||
"""将收集的日志保存到打包目录"""
|
||||
lines = self._log_lines.pop(task_id, None)
|
||||
if not lines:
|
||||
return
|
||||
|
||||
log_path = build_dir / "build.log"
|
||||
with open(log_path, "w", encoding="utf-8") as f:
|
||||
for entry in lines:
|
||||
ts = entry["timestamp"]
|
||||
level = entry["level"].upper()
|
||||
msg = entry["message"]
|
||||
f.write(f"[{ts}] [{level}] {msg}\n")
|
||||
|
||||
def get_log(self, build_dir: Path) -> str:
|
||||
"""读取已保存的打包日志"""
|
||||
log_path = build_dir / "build.log"
|
||||
if log_path.exists():
|
||||
return log_path.read_text(encoding="utf-8")
|
||||
return ""
|
||||
|
||||
|
||||
# 全局单例
|
||||
log_streamer = LogStreamer()
|
||||
|
||||
Reference in New Issue
Block a user