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:
@@ -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():
|
||||
|
||||
@@ -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 文件"""
|
||||
|
||||
Reference in New Issue
Block a user