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:
shen
2026-06-08 11:23:15 +08:00
parent 898ec01560
commit 75363ee276
6 changed files with 243 additions and 15 deletions
+51
View File
@@ -298,6 +298,57 @@ async def update_build_settings(settings: BuildConfigUpdate, db: Session = Depen
return {"message": "打包设置已更新"}
# 版本号配置 API
@router.get("/versions")
async def get_versions():
"""获取 App_Ver 和 Build_Ver"""
from ..config import AUTOPACKING_DIR
start_build_path = AUTOPACKING_DIR / "start_build_app.py"
app_ver = "2.180.0"
build_ver = "2.180.0.0"
if start_build_path.exists():
content = start_build_path.read_text(encoding="utf-8")
for line in content.split("\n"):
if line.startswith("App_Ver") and '"' in line:
app_ver = line.split('"')[1]
elif line.startswith("Build_Ver") and '"' in line:
build_ver = line.split('"')[1]
return {"app_ver": app_ver, "build_ver": build_ver}
@router.put("/versions")
async def update_versions(data: dict):
"""更新 App_Ver 和 Build_Ver"""
from ..config import AUTOPACKING_DIR
app_ver = data.get("app_ver", "").strip()
build_ver = data.get("build_ver", "").strip()
if not app_ver or not build_ver:
raise HTTPException(status_code=400, detail="版本号不能为空")
start_build_path = AUTOPACKING_DIR / "start_build_app.py"
if not start_build_path.exists():
raise HTTPException(status_code=404, detail="start_build_app.py 不存在")
async with _config_lock:
content = start_build_path.read_text(encoding="utf-8")
new_lines = []
for line in content.split("\n"):
if line.startswith("App_Ver") and '"' in line:
new_lines.append(f'App_Ver = "{app_ver}"')
elif line.startswith("Build_Ver") and '"' in line:
new_lines.append(f'Build_Ver = "{build_ver}"')
else:
new_lines.append(line)
start_build_path.write_text("\n".join(new_lines), encoding="utf-8")
return {"message": "版本号已更新", "app_ver": app_ver, "build_ver": build_ver}
# 上传配置 API
@router.get("/upload")
async def get_upload_config():
+30
View File
@@ -101,6 +101,36 @@ async def cancel_task(task_id: str, db: Session = Depends(get_db)):
return {"message": "任务已取消"}
@router.get("/{task_id}/log")
async def get_build_log(task_id: str, db: Session = Depends(get_db)):
"""获取打包日志"""
task = db.query(Task).filter(Task.id == task_id).first()
if not task:
raise HTTPException(status_code=404, detail="任务不存在")
from ..services.log_streamer import log_streamer
# 先从内存中获取(任务运行中)
lines = log_streamer._log_lines.get(task_id)
if lines:
content = ""
for entry in lines:
ts = entry["timestamp"]
level = entry["level"].upper()
msg = entry["message"]
content += f"[{ts}] [{level}] {msg}\n"
return {"log": content}
# 从文件获取(任务已完成)
if task.build_dir:
from pathlib import Path
log_path = Path(task.build_dir) / "build.log"
if log_path.exists():
return {"log": log_path.read_text(encoding="utf-8")}
return {"log": ""}
@router.get("/{task_id}/dsym")
async def download_dsym(task_id: str, db: Session = Depends(get_db)):
"""下载 dSYM 文件"""