1163 lines
48 KiB
Python
1163 lines
48 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
独立的Issue同步Web服务
|
||
避免与主项目的Pydantic兼容性问题
|
||
"""
|
||
|
||
import time
|
||
import sys
|
||
import os
|
||
from typing import Dict, Any, Optional
|
||
|
||
# 添加issue_sync_module到Python路径
|
||
issue_sync_path = os.path.join(os.path.dirname(__file__), 'issue_sync_module')
|
||
if issue_sync_path not in sys.path:
|
||
sys.path.append(issue_sync_path)
|
||
|
||
try:
|
||
from fastapi import FastAPI, BackgroundTasks, Body, Request
|
||
from pydantic import BaseModel
|
||
import uvicorn
|
||
from clients.sync_service import IssueSyncService
|
||
from webhook.webhook_handler import WebhookHandler
|
||
DEPENDENCIES_AVAILABLE = True
|
||
except ImportError as e:
|
||
print("缺少依赖: {}".format(str(e)))
|
||
DEPENDENCIES_AVAILABLE = False
|
||
|
||
app = FastAPI(
|
||
title="Issue同步服务",
|
||
description="在GitHub、Gitee、GitLink之间同步Issues和评论",
|
||
version="1.0.0"
|
||
)
|
||
|
||
# 初始化Webhook处理器
|
||
webhook_handler = WebhookHandler() if DEPENDENCIES_AVAILABLE else None
|
||
|
||
class IssueSyncRequest(BaseModel):
|
||
"""Issue同步请求"""
|
||
source_org: str
|
||
source_repo: str
|
||
source_platform: str # github, gitee, gitlink
|
||
target_org: str
|
||
target_repo: str
|
||
target_platform: str # github, gitee, gitlink
|
||
sync_comments: bool = False
|
||
sync_milestones: bool = True # 添加里程碑同步选项,默认启用
|
||
update_existing: bool = True # 是否更新已存在的Issue,默认启用
|
||
enable_deletion: bool = False # 是否启用Issue删除同步,默认禁用
|
||
|
||
class CommentSyncRequest(BaseModel):
|
||
"""评论同步请求"""
|
||
source_org: str
|
||
source_repo: str
|
||
source_platform: str
|
||
target_org: str
|
||
target_repo: str
|
||
target_platform: str
|
||
issue_title: str
|
||
|
||
class BatchCommentSyncRequest(BaseModel):
|
||
"""批量评论同步请求"""
|
||
source_org: str
|
||
source_repo: str
|
||
source_platform: str
|
||
target_org: str
|
||
target_repo: str
|
||
target_platform: str
|
||
|
||
class MilestoneSyncRequest(BaseModel):
|
||
"""里程碑同步请求"""
|
||
source_org: str
|
||
source_repo: str
|
||
source_platform: str # github, gitee, gitlink
|
||
target_org: str
|
||
target_repo: str
|
||
target_platform: str # github, gitee, gitlink
|
||
|
||
class BidirectionalSyncRequest(BaseModel):
|
||
"""双向同步请求"""
|
||
platform_a_org: str
|
||
platform_a_repo: str
|
||
platform_a: str # github, gitee, gitlink
|
||
platform_b_org: str
|
||
platform_b_repo: str
|
||
platform_b: str # github, gitee, gitlink
|
||
conflict_strategy: str = 'prefer_newer' # prefer_newer, prefer_gitlink, prefer_github, prefer_gitee
|
||
sync_milestones: bool = True
|
||
sync_comments: bool = False # 仅GitLink相关时启用
|
||
enable_deletion: bool = False
|
||
|
||
@app.get("/")
|
||
async def root():
|
||
"""根路径"""
|
||
return {
|
||
"service": "Issue同步服务",
|
||
"version": "1.0.0",
|
||
"status": "运行中",
|
||
"dependencies_available": DEPENDENCIES_AVAILABLE,
|
||
"endpoints": {
|
||
"docs": "/docs",
|
||
"status": "/status",
|
||
"sync": "/sync",
|
||
"sync_bidirectional": "/sync/bidirectional",
|
||
"sync_comments": "/sync/comments",
|
||
"sync_comments_batch": "/sync/comments/batch",
|
||
"sync_milestones": "/sync/milestones"
|
||
}
|
||
}
|
||
|
||
@app.get("/status")
|
||
async def get_status():
|
||
"""获取服务状态"""
|
||
return {
|
||
"success": True,
|
||
"data": {
|
||
"service_available": DEPENDENCIES_AVAILABLE,
|
||
"supported_platforms": ["github", "gitee", "gitlink"],
|
||
"supported_directions": [
|
||
"github → gitee",
|
||
"gitee → github",
|
||
"gitlink → github",
|
||
"gitlink → gitee",
|
||
"github → gitlink",
|
||
"gitee → gitlink"
|
||
],
|
||
"bidirectional_sync_support": [
|
||
"GitLink ↔ GitHub",
|
||
"GitLink ↔ Gitee",
|
||
"GitHub ↔ Gitee"
|
||
],
|
||
"milestone_sync_support": {
|
||
"gitee → gitlink": True,
|
||
"gitlink → gitee": True,
|
||
"github → gitlink": True,
|
||
"other_directions": "可根据需要扩展"
|
||
},
|
||
"features": [
|
||
"单向Issue同步",
|
||
"双向Issue同步",
|
||
"Issue内容更新",
|
||
"Issue删除同步",
|
||
"评论同步",
|
||
"里程碑双向同步",
|
||
"智能冲突解决",
|
||
"批量操作"
|
||
],
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
},
|
||
"message": "服务状态获取成功"
|
||
}
|
||
|
||
@app.post("/sync")
|
||
async def sync_issues(
|
||
background_tasks: BackgroundTasks,
|
||
request: IssueSyncRequest = Body(..., description='同步请求参数')
|
||
):
|
||
"""执行Issue同步"""
|
||
try:
|
||
if not DEPENDENCIES_AVAILABLE:
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步服务依赖不可用",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证参数
|
||
if not request.source_org or not request.source_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "源仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
if not request.target_org or not request.target_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "目标仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证平台类型
|
||
valid_platforms = ["github", "gitee", "gitlink"]
|
||
if request.source_platform not in valid_platforms or request.target_platform not in valid_platforms:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的平台类型。支持的平台: {}".format(valid_platforms),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 创建同步服务
|
||
sync_service = IssueSyncService()
|
||
|
||
# 根据平台组合执行同步
|
||
sync_method = get_sync_method(sync_service, request.source_platform, request.target_platform)
|
||
if not sync_method:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的同步方向: {} → {}".format(request.source_platform, request.target_platform),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 在后台执行同步
|
||
background_tasks.add_task(
|
||
execute_sync_task,
|
||
sync_method,
|
||
request.source_org,
|
||
request.source_repo,
|
||
request.target_org,
|
||
request.target_repo,
|
||
request.sync_comments,
|
||
request.sync_milestones,
|
||
request.update_existing,
|
||
request.enable_deletion
|
||
)
|
||
|
||
return {
|
||
"success": True,
|
||
"message": "Issue同步任务已启动: {} → {}".format(request.source_platform, request.target_platform),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S'),
|
||
"task_info": {
|
||
"source": "{}/{}".format(request.source_org, request.source_repo),
|
||
"target": "{}/{}".format(request.target_org, request.target_repo),
|
||
"sync_comments": request.sync_comments,
|
||
"sync_milestones": request.sync_milestones,
|
||
"update_existing": request.update_existing,
|
||
"enable_deletion": request.enable_deletion
|
||
}
|
||
}
|
||
|
||
except Exception as e:
|
||
print("Issue同步失败: {}".format(str(e)))
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步失败: {}".format(str(e)),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
@app.post("/sync/immediate")
|
||
async def sync_issues_immediate(
|
||
request: IssueSyncRequest = Body(..., description='同步请求参数')
|
||
):
|
||
"""立即执行Issue同步并返回结果"""
|
||
try:
|
||
if not DEPENDENCIES_AVAILABLE:
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步服务依赖不可用",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证参数
|
||
if not request.source_org or not request.source_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "源仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
if not request.target_org or not request.target_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "目标仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证平台类型
|
||
valid_platforms = ["github", "gitee", "gitlink"]
|
||
if request.source_platform not in valid_platforms or request.target_platform not in valid_platforms:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的平台类型。支持的平台: {}".format(valid_platforms),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 创建同步服务
|
||
sync_service = IssueSyncService()
|
||
|
||
# 根据平台组合执行同步
|
||
sync_method = get_sync_method(sync_service, request.source_platform, request.target_platform)
|
||
if not sync_method:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的同步方向: {} → {}".format(request.source_platform, request.target_platform),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
print("🚀 开始执行Issue同步: {}/{} → {}/{}".format(
|
||
request.source_org, request.source_repo, request.target_org, request.target_repo))
|
||
print(" • 平台: {} → {}".format(request.source_platform, request.target_platform))
|
||
print(" • 评论同步: {}".format("启用" if request.sync_comments else "禁用"))
|
||
print(" • 里程碑同步: {}".format("启用" if request.sync_milestones else "禁用"))
|
||
print(" • 更新已存在Issue: {}".format("启用" if request.update_existing else "禁用"))
|
||
print(" • Issue删除同步: {}".format("启用" if request.enable_deletion else "禁用"))
|
||
|
||
# 检查同步方法支持的参数
|
||
import inspect
|
||
sig = inspect.signature(sync_method)
|
||
|
||
# 构建参数字典
|
||
kwargs = {}
|
||
if 'sync_comments' in sig.parameters:
|
||
kwargs['sync_comments'] = request.sync_comments
|
||
if 'sync_milestones' in sig.parameters:
|
||
kwargs['sync_milestones'] = request.sync_milestones
|
||
if 'update_existing' in sig.parameters:
|
||
kwargs['update_existing'] = request.update_existing
|
||
if 'enable_deletion' in sig.parameters:
|
||
kwargs['enable_deletion'] = request.enable_deletion
|
||
|
||
# 立即执行同步
|
||
result = sync_method(
|
||
request.source_org,
|
||
request.source_repo,
|
||
request.target_org,
|
||
request.target_repo,
|
||
**kwargs
|
||
)
|
||
|
||
if result:
|
||
print("✅ Issue同步成功: {}/{} → {}/{}".format(
|
||
request.source_org, request.source_repo, request.target_org, request.target_repo))
|
||
return {
|
||
"success": True,
|
||
"message": "Issue同步成功完成: {} → {}".format(request.source_platform, request.target_platform),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S'),
|
||
"result": {
|
||
"sync_success": True,
|
||
"source": "{}/{}".format(request.source_org, request.source_repo),
|
||
"target": "{}/{}".format(request.target_org, request.target_repo),
|
||
"platform_direction": "{} → {}".format(request.source_platform, request.target_platform),
|
||
"options_applied": {
|
||
"sync_comments": request.sync_comments,
|
||
"sync_milestones": request.sync_milestones,
|
||
"update_existing": request.update_existing,
|
||
"enable_deletion": request.enable_deletion
|
||
}
|
||
}
|
||
}
|
||
else:
|
||
print("❌ Issue同步失败: {}/{} → {}/{}".format(
|
||
request.source_org, request.source_repo, request.target_org, request.target_repo))
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步执行失败",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
except Exception as e:
|
||
print("💥 Issue同步任务执行异常: {}".format(str(e)))
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步失败: {}".format(str(e)),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
@app.post("/sync/comments")
|
||
async def sync_issue_comments(
|
||
background_tasks: BackgroundTasks,
|
||
request: CommentSyncRequest = Body(..., description='评论同步请求参数')
|
||
):
|
||
"""同步指定Issue的评论"""
|
||
try:
|
||
if not DEPENDENCIES_AVAILABLE:
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步服务依赖不可用",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
if not request.issue_title:
|
||
return {
|
||
"success": False,
|
||
"message": "Issue标题不能为空",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
sync_service = IssueSyncService()
|
||
|
||
# 根据平台组合选择评论同步方法
|
||
comment_method = get_comment_sync_method(sync_service, request.source_platform, request.target_platform)
|
||
if not comment_method:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的评论同步方向: {} → {}".format(request.source_platform, request.target_platform),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 在后台执行评论同步
|
||
background_tasks.add_task(
|
||
execute_comment_sync_task,
|
||
comment_method,
|
||
request.source_org,
|
||
request.source_repo,
|
||
request.target_org,
|
||
request.target_repo,
|
||
request.issue_title
|
||
)
|
||
|
||
return {
|
||
"success": True,
|
||
"message": "评论同步任务已启动: {}".format(request.issue_title),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S'),
|
||
"task_info": {
|
||
"source": "{}/{}".format(request.source_org, request.source_repo),
|
||
"target": "{}/{}".format(request.target_org, request.target_repo),
|
||
"issue_title": request.issue_title
|
||
}
|
||
}
|
||
|
||
except Exception as e:
|
||
print("评论同步失败: {}".format(str(e)))
|
||
return {
|
||
"success": False,
|
||
"message": "评论同步失败: {}".format(str(e)),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
@app.post("/sync/comments/batch")
|
||
async def sync_all_comments(
|
||
background_tasks: BackgroundTasks,
|
||
request: BatchCommentSyncRequest = Body(..., description='批量评论同步请求参数')
|
||
):
|
||
"""批量同步所有Issue的评论"""
|
||
try:
|
||
if not DEPENDENCIES_AVAILABLE:
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步服务依赖不可用",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
sync_service = IssueSyncService()
|
||
|
||
# 在后台执行批量评论同步
|
||
background_tasks.add_task(
|
||
execute_batch_comment_sync_task,
|
||
sync_service,
|
||
request.source_org,
|
||
request.source_repo,
|
||
request.source_platform,
|
||
request.target_org,
|
||
request.target_repo,
|
||
request.target_platform
|
||
)
|
||
|
||
return {
|
||
"success": True,
|
||
"message": "批量评论同步任务已启动: {} → {}".format(request.source_platform, request.target_platform),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S'),
|
||
"task_info": {
|
||
"source": "{}/{}".format(request.source_org, request.source_repo),
|
||
"target": "{}/{}".format(request.target_org, request.target_repo)
|
||
}
|
||
}
|
||
|
||
except Exception as e:
|
||
print("批量评论同步失败: {}".format(str(e)))
|
||
return {
|
||
"success": False,
|
||
"message": "批量评论同步失败: {}".format(str(e)),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
@app.post("/sync/milestones")
|
||
async def sync_milestones(
|
||
background_tasks: BackgroundTasks,
|
||
request: MilestoneSyncRequest = Body(..., description='里程碑同步请求参数')
|
||
):
|
||
"""执行里程碑同步"""
|
||
try:
|
||
if not DEPENDENCIES_AVAILABLE:
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步服务依赖不可用",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证参数
|
||
if not request.source_org or not request.source_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "源仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
if not request.target_org or not request.target_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "目标仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证平台类型
|
||
valid_platforms = ["github", "gitee", "gitlink"]
|
||
if request.source_platform not in valid_platforms or request.target_platform not in valid_platforms:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的平台类型。支持的平台: {}".format(valid_platforms),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 创建同步服务
|
||
sync_service = IssueSyncService()
|
||
|
||
# 根据平台组合获取里程碑同步方法
|
||
milestone_method = get_milestone_sync_method(sync_service, request.source_platform, request.target_platform)
|
||
if not milestone_method:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的里程碑同步方向: {} → {}".format(request.source_platform, request.target_platform),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 在后台执行里程碑同步
|
||
background_tasks.add_task(
|
||
execute_milestone_sync_task,
|
||
milestone_method,
|
||
request.source_org,
|
||
request.source_repo,
|
||
request.target_org,
|
||
request.target_repo,
|
||
request.source_platform,
|
||
request.target_platform
|
||
)
|
||
|
||
return {
|
||
"success": True,
|
||
"message": "里程碑同步任务已启动: {} → {}".format(request.source_platform, request.target_platform),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S'),
|
||
"task_info": {
|
||
"source": "{}/{}".format(request.source_org, request.source_repo),
|
||
"target": "{}/{}".format(request.target_org, request.target_repo),
|
||
"sync_direction": "{} → {}".format(request.source_platform, request.target_platform)
|
||
}
|
||
}
|
||
|
||
except Exception as e:
|
||
print("里程碑同步失败: {}".format(str(e)))
|
||
return {
|
||
"success": False,
|
||
"message": "里程碑同步失败: {}".format(str(e)),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
@app.post("/sync/bidirectional")
|
||
async def bidirectional_sync(
|
||
background_tasks: BackgroundTasks,
|
||
request: BidirectionalSyncRequest = Body(..., description='双向同步请求参数')
|
||
):
|
||
"""执行双向Issue同步"""
|
||
try:
|
||
if not DEPENDENCIES_AVAILABLE:
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步服务依赖不可用",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证参数
|
||
if not request.platform_a_org or not request.platform_a_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "平台A仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
if not request.platform_b_org or not request.platform_b_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "平台B仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证平台类型
|
||
valid_platforms = ["github", "gitee", "gitlink"]
|
||
if request.platform_a not in valid_platforms or request.platform_b not in valid_platforms:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的平台类型。支持的平台: {}".format(valid_platforms),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证不能选择相同平台
|
||
if request.platform_a == request.platform_b:
|
||
return {
|
||
"success": False,
|
||
"message": "双向同步的两个平台不能相同",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 创建同步服务
|
||
sync_service = IssueSyncService()
|
||
|
||
# 根据平台组合获取双向同步方法
|
||
bidirectional_method = get_bidirectional_sync_method(sync_service, request.platform_a, request.platform_b)
|
||
if not bidirectional_method:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的双向同步平台组合: {} ↔ {}".format(request.platform_a, request.platform_b),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 在后台执行双向同步
|
||
background_tasks.add_task(
|
||
execute_bidirectional_sync_task,
|
||
bidirectional_method,
|
||
request.platform_a_org,
|
||
request.platform_a_repo,
|
||
request.platform_a,
|
||
request.platform_b_org,
|
||
request.platform_b_repo,
|
||
request.platform_b,
|
||
request.conflict_strategy,
|
||
request.sync_milestones,
|
||
request.sync_comments,
|
||
request.enable_deletion
|
||
)
|
||
|
||
return {
|
||
"success": True,
|
||
"message": "双向同步任务已启动: {} ↔ {}".format(request.platform_a, request.platform_b),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S'),
|
||
"task_info": {
|
||
"platform_a": "{}/{}".format(request.platform_a_org, request.platform_a_repo),
|
||
"platform_b": "{}/{}".format(request.platform_b_org, request.platform_b_repo),
|
||
"conflict_strategy": request.conflict_strategy,
|
||
"sync_milestones": request.sync_milestones,
|
||
"sync_comments": request.sync_comments,
|
||
"enable_deletion": request.enable_deletion
|
||
}
|
||
}
|
||
|
||
except Exception as e:
|
||
print("双向同步失败: {}".format(str(e)))
|
||
return {
|
||
"success": False,
|
||
"message": "双向同步失败: {}".format(str(e)),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
@app.post("/sync/bidirectional/immediate")
|
||
async def bidirectional_sync_immediate(
|
||
request: BidirectionalSyncRequest = Body(..., description='双向同步请求参数')
|
||
):
|
||
"""立即执行双向Issue同步并返回结果"""
|
||
try:
|
||
if not DEPENDENCIES_AVAILABLE:
|
||
return {
|
||
"success": False,
|
||
"message": "Issue同步服务依赖不可用",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证参数
|
||
if not request.platform_a_org or not request.platform_a_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "平台A仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
if not request.platform_b_org or not request.platform_b_repo:
|
||
return {
|
||
"success": False,
|
||
"message": "平台B仓库信息不完整",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证平台类型
|
||
valid_platforms = ["github", "gitee", "gitlink"]
|
||
if request.platform_a not in valid_platforms or request.platform_b not in valid_platforms:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的平台类型。支持的平台: {}".format(valid_platforms),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 验证不能选择相同平台
|
||
if request.platform_a == request.platform_b:
|
||
return {
|
||
"success": False,
|
||
"message": "双向同步的两个平台不能相同",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 创建同步服务
|
||
sync_service = IssueSyncService()
|
||
|
||
# 根据平台组合获取双向同步方法
|
||
bidirectional_method = get_bidirectional_sync_method(sync_service, request.platform_a, request.platform_b)
|
||
if not bidirectional_method:
|
||
return {
|
||
"success": False,
|
||
"message": "不支持的双向同步平台组合: {} ↔ {}".format(request.platform_a, request.platform_b),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
print("🔄 开始执行双向同步: {} ↔ {}".format(request.platform_a, request.platform_b))
|
||
print(" • 平台A: {}/{}".format(request.platform_a_org, request.platform_a_repo))
|
||
print(" • 平台B: {}/{}".format(request.platform_b_org, request.platform_b_repo))
|
||
print(" • 冲突策略: {}".format(request.conflict_strategy))
|
||
print(" • 里程碑同步: {}".format("启用" if request.sync_milestones else "禁用"))
|
||
print(" • 评论同步: {}".format("启用" if request.sync_comments else "禁用"))
|
||
print(" • Issue删除同步: {}".format("启用" if request.enable_deletion else "禁用"))
|
||
|
||
# 检查双向同步方法支持的参数
|
||
import inspect
|
||
sig = inspect.signature(bidirectional_method)
|
||
|
||
# 构建参数字典
|
||
kwargs = {}
|
||
if 'conflict_strategy' in sig.parameters:
|
||
kwargs['conflict_strategy'] = request.conflict_strategy
|
||
if 'sync_milestones' in sig.parameters:
|
||
kwargs['sync_milestones'] = request.sync_milestones
|
||
if 'sync_comments' in sig.parameters:
|
||
kwargs['sync_comments'] = request.sync_comments
|
||
if 'enable_deletion' in sig.parameters:
|
||
kwargs['enable_deletion'] = request.enable_deletion
|
||
|
||
# 根据方法名和平台顺序调用相应的双向同步方法
|
||
method_name = bidirectional_method.__name__
|
||
|
||
if method_name == 'bidirectional_sync_gitlink_github':
|
||
# 确定GitLink和GitHub的顺序
|
||
if request.platform_a == 'gitlink':
|
||
result = bidirectional_method(
|
||
request.platform_a_org, request.platform_a_repo, # GitLink
|
||
request.platform_b_org, request.platform_b_repo, # GitHub
|
||
**kwargs
|
||
)
|
||
else: # GitHub是平台A
|
||
result = bidirectional_method(
|
||
request.platform_b_org, request.platform_b_repo, # GitLink
|
||
request.platform_a_org, request.platform_a_repo, # GitHub
|
||
**kwargs
|
||
)
|
||
elif method_name == 'bidirectional_sync_gitlink_gitee':
|
||
# 确定GitLink和Gitee的顺序
|
||
if request.platform_a == 'gitlink':
|
||
result = bidirectional_method(
|
||
request.platform_a_org, request.platform_a_repo, # GitLink
|
||
request.platform_b_org, request.platform_b_repo, # Gitee
|
||
**kwargs
|
||
)
|
||
else: # Gitee是平台A
|
||
result = bidirectional_method(
|
||
request.platform_b_org, request.platform_b_repo, # GitLink
|
||
request.platform_a_org, request.platform_a_repo, # Gitee
|
||
**kwargs
|
||
)
|
||
elif method_name == 'bidirectional_sync_github_gitee':
|
||
# 确定GitHub和Gitee的顺序
|
||
if request.platform_a == 'github':
|
||
result = bidirectional_method(
|
||
request.platform_a_org, request.platform_a_repo, # GitHub
|
||
request.platform_b_org, request.platform_b_repo, # Gitee
|
||
**kwargs
|
||
)
|
||
else: # Gitee是平台A
|
||
result = bidirectional_method(
|
||
request.platform_b_org, request.platform_b_repo, # GitHub
|
||
request.platform_a_org, request.platform_a_repo, # Gitee
|
||
**kwargs
|
||
)
|
||
else:
|
||
print("❌ 未知的双向同步方法: {}".format(method_name))
|
||
return {
|
||
"success": False,
|
||
"message": "未知的双向同步方法: {}".format(method_name),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
if result and isinstance(result, dict):
|
||
print("✅ 双向同步完成!")
|
||
|
||
# 分析同步结果
|
||
total_created = 0
|
||
total_updated = 0
|
||
total_conflicts = result.get('conflicts_resolved', 0)
|
||
total_processed = result.get('total_processed', 0)
|
||
|
||
# 统计各方向的结果
|
||
direction_results = {}
|
||
for direction_key in result:
|
||
if '_to_' in direction_key and isinstance(result[direction_key], dict):
|
||
direction_stats = result[direction_key]
|
||
direction_name = direction_key.replace('_', ' → ').title()
|
||
direction_results[direction_name] = direction_stats
|
||
total_created += direction_stats.get('created', 0)
|
||
total_updated += direction_stats.get('updated', 0)
|
||
|
||
return {
|
||
"success": True,
|
||
"message": "双向同步成功完成: {} ↔ {}".format(request.platform_a, request.platform_b),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S'),
|
||
"result": {
|
||
"sync_success": True,
|
||
"platform_a": "{}/{}".format(request.platform_a_org, request.platform_a_repo),
|
||
"platform_b": "{}/{}".format(request.platform_b_org, request.platform_b_repo),
|
||
"platform_combination": "{} ↔ {}".format(request.platform_a, request.platform_b),
|
||
"summary": {
|
||
"total_processed": total_processed,
|
||
"total_created": total_created,
|
||
"total_updated": total_updated,
|
||
"conflicts_resolved": total_conflicts
|
||
},
|
||
"direction_details": direction_results,
|
||
"options_applied": {
|
||
"conflict_strategy": request.conflict_strategy,
|
||
"sync_milestones": request.sync_milestones,
|
||
"sync_comments": request.sync_comments,
|
||
"enable_deletion": request.enable_deletion
|
||
},
|
||
"raw_result": result
|
||
}
|
||
}
|
||
else:
|
||
print("❌ 双向同步失败")
|
||
return {
|
||
"success": False,
|
||
"message": "双向同步执行失败",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
except Exception as e:
|
||
print("💥 双向同步任务执行异常: {}".format(str(e)))
|
||
return {
|
||
"success": False,
|
||
"message": "双向同步失败: {}".format(str(e)),
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
def get_sync_method(sync_service: IssueSyncService, source_platform: str, target_platform: str):
|
||
"""根据平台获取对应的同步方法"""
|
||
sync_mapping = {
|
||
("github", "gitee"): sync_service.sync_github_to_gitee,
|
||
("gitee", "github"): sync_service.sync_gitee_to_github,
|
||
("gitlink", "github"): sync_service.sync_gitlink_to_github,
|
||
("gitlink", "gitee"): sync_service.sync_gitlink_to_gitee,
|
||
("github", "gitlink"): sync_service.sync_github_to_gitlink,
|
||
("gitee", "gitlink"): sync_service.sync_gitee_to_gitlink,
|
||
}
|
||
|
||
return sync_mapping.get((source_platform, target_platform))
|
||
|
||
def get_comment_sync_method(sync_service: IssueSyncService, source_platform: str, target_platform: str):
|
||
"""根据平台获取对应的评论同步方法"""
|
||
comment_mapping = {
|
||
("github", "gitee"): sync_service.sync_issue_comments_github_to_gitee,
|
||
("gitee", "github"): sync_service.sync_issue_comments_gitee_to_github,
|
||
("gitlink", "github"): sync_service.sync_issue_comments_gitlink_to_github,
|
||
("gitlink", "gitee"): sync_service.sync_issue_comments_gitlink_to_gitee,
|
||
}
|
||
|
||
return comment_mapping.get((source_platform, target_platform))
|
||
|
||
def get_milestone_sync_method(sync_service: IssueSyncService, source_platform: str, target_platform: str):
|
||
"""根据平台获取对应的里程碑同步方法"""
|
||
milestone_mapping = {
|
||
("gitee", "gitlink"): sync_service.sync_milestones_gitee_to_gitlink,
|
||
("gitlink", "gitee"): sync_service.sync_milestones_gitlink_to_gitee,
|
||
("github", "gitlink"): sync_service.sync_milestones_github_to_gitlink,
|
||
}
|
||
|
||
return milestone_mapping.get((source_platform, target_platform))
|
||
|
||
def get_bidirectional_sync_method(sync_service: IssueSyncService, platform_a: str, platform_b: str):
|
||
"""根据平台组合获取对应的双向同步方法"""
|
||
# 双向同步支持的平台组合(顺序不重要)
|
||
bidirectional_mapping = {
|
||
("gitlink", "github"): sync_service.bidirectional_sync_gitlink_github,
|
||
("github", "gitlink"): sync_service.bidirectional_sync_gitlink_github,
|
||
("gitlink", "gitee"): sync_service.bidirectional_sync_gitlink_gitee,
|
||
("gitee", "gitlink"): sync_service.bidirectional_sync_gitlink_gitee,
|
||
("github", "gitee"): sync_service.bidirectional_sync_github_gitee,
|
||
("gitee", "github"): sync_service.bidirectional_sync_github_gitee,
|
||
}
|
||
|
||
return bidirectional_mapping.get((platform_a, platform_b))
|
||
|
||
async def execute_sync_task(sync_method, source_org: str, source_repo: str,
|
||
target_org: str, target_repo: str, sync_comments: bool, sync_milestones: bool = True,
|
||
update_existing: bool = True, enable_deletion: bool = False):
|
||
"""执行同步任务"""
|
||
try:
|
||
print("🚀 开始执行Issue同步: {}/{} → {}/{}".format(source_org, source_repo, target_org, target_repo))
|
||
print(" • 评论同步: {}".format("启用" if sync_comments else "禁用"))
|
||
print(" • 里程碑同步: {}".format("启用" if sync_milestones else "禁用"))
|
||
print(" • 更新已存在Issue: {}".format("启用" if update_existing else "禁用"))
|
||
print(" • Issue删除同步: {}".format("启用" if enable_deletion else "禁用"))
|
||
|
||
# 检查同步方法支持的参数
|
||
import inspect
|
||
sig = inspect.signature(sync_method)
|
||
|
||
# 构建参数字典
|
||
kwargs = {}
|
||
if 'sync_comments' in sig.parameters:
|
||
kwargs['sync_comments'] = sync_comments
|
||
if 'sync_milestones' in sig.parameters:
|
||
kwargs['sync_milestones'] = sync_milestones
|
||
if 'update_existing' in sig.parameters:
|
||
kwargs['update_existing'] = update_existing
|
||
if 'enable_deletion' in sig.parameters:
|
||
kwargs['enable_deletion'] = enable_deletion
|
||
|
||
# 执行同步
|
||
result = sync_method(source_org, source_repo, target_org, target_repo, **kwargs)
|
||
|
||
if result:
|
||
print("✅ Issue同步成功: {}/{} → {}/{}".format(source_org, source_repo, target_org, target_repo))
|
||
else:
|
||
print("❌ Issue同步失败: {}/{} → {}/{}".format(source_org, source_repo, target_org, target_repo))
|
||
|
||
except Exception as e:
|
||
print("💥 Issue同步任务执行异常: {}".format(str(e)))
|
||
|
||
async def execute_comment_sync_task(comment_method, source_org: str, source_repo: str,
|
||
target_org: str, target_repo: str, issue_title: str):
|
||
"""执行评论同步任务"""
|
||
try:
|
||
print("🚀 开始执行评论同步: {}".format(issue_title))
|
||
result = comment_method(source_org, source_repo, target_org, target_repo, issue_title)
|
||
|
||
if result:
|
||
print("✅ 评论同步成功: {}".format(issue_title))
|
||
else:
|
||
print("❌ 评论同步失败: {}".format(issue_title))
|
||
|
||
except Exception as e:
|
||
print("💥 评论同步任务执行异常: {}".format(str(e)))
|
||
|
||
async def execute_batch_comment_sync_task(sync_service: IssueSyncService,
|
||
source_org: str, source_repo: str, source_platform: str,
|
||
target_org: str, target_repo: str, target_platform: str):
|
||
"""执行批量评论同步任务"""
|
||
try:
|
||
print("🚀 开始执行批量评论同步: {} → {}".format(source_platform, target_platform))
|
||
result = sync_service.sync_all_issue_comments(
|
||
source_org, source_repo, source_platform,
|
||
target_org, target_repo, target_platform
|
||
)
|
||
|
||
if result:
|
||
print("✅ 批量评论同步成功: {} → {}".format(source_platform, target_platform))
|
||
else:
|
||
print("❌ 批量评论同步失败: {} → {}".format(source_platform, target_platform))
|
||
|
||
except Exception as e:
|
||
print("💥 批量评论同步任务执行异常: {}".format(str(e)))
|
||
|
||
async def execute_milestone_sync_task(milestone_method, source_org: str, source_repo: str,
|
||
target_org: str, target_repo: str,
|
||
source_platform: str, target_platform: str):
|
||
"""执行里程碑同步任务"""
|
||
try:
|
||
print("🎯 开始执行里程碑同步: {} → {}".format(source_platform, target_platform))
|
||
print(" • 源仓库: {}/{}".format(source_org, source_repo))
|
||
print(" • 目标仓库: {}/{}".format(target_org, target_repo))
|
||
|
||
result = milestone_method(source_org, source_repo, target_org, target_repo)
|
||
|
||
if result and isinstance(result, dict):
|
||
print("✅ 里程碑同步完成!")
|
||
print("📊 同步统计:")
|
||
print(" • 源平台里程碑总数: {}".format(result.get('total_gitee_milestones', result.get('total_github_milestones', result.get('total_gitlink_milestones', 0)))))
|
||
print(" • 目标平台已存在: {}".format(result.get('existing_in_gitlink', result.get('existing_in_gitee', 0))))
|
||
print(" • 成功创建: {}".format(result.get('created_in_gitlink', result.get('created_in_gitee', 0))))
|
||
print(" • 创建失败: {}".format(result.get('failed_to_create', 0)))
|
||
print(" • 建立映射关系: {}".format(len(result.get('milestone_mapping', {}))))
|
||
|
||
if result.get('created_milestones'):
|
||
print("📝 已创建的里程碑:")
|
||
for milestone in result['created_milestones']:
|
||
print(" - '{}'".format(milestone.get('gitee_title', milestone.get('github_title', milestone.get('gitlink_title', '未知')))))
|
||
else:
|
||
print("❌ 里程碑同步失败")
|
||
|
||
except Exception as e:
|
||
print("💥 里程碑同步任务执行异常: {}".format(str(e)))
|
||
|
||
async def execute_bidirectional_sync_task(bidirectional_method,
|
||
platform_a_org: str, platform_a_repo: str, platform_a: str,
|
||
platform_b_org: str, platform_b_repo: str, platform_b: str,
|
||
conflict_strategy: str, sync_milestones: bool,
|
||
sync_comments: bool, enable_deletion: bool):
|
||
"""执行双向同步任务"""
|
||
try:
|
||
print("🔄 开始执行双向同步: {} ↔ {}".format(platform_a, platform_b))
|
||
print(" • 平台A: {}/{}".format(platform_a_org, platform_a_repo))
|
||
print(" • 平台B: {}/{}".format(platform_b_org, platform_b_repo))
|
||
print(" • 冲突策略: {}".format(conflict_strategy))
|
||
print(" • 里程碑同步: {}".format("启用" if sync_milestones else "禁用"))
|
||
print(" • 评论同步: {}".format("启用" if sync_comments else "禁用"))
|
||
print(" • Issue删除同步: {}".format("启用" if enable_deletion else "禁用"))
|
||
|
||
# 检查双向同步方法支持的参数
|
||
import inspect
|
||
sig = inspect.signature(bidirectional_method)
|
||
|
||
# 构建参数字典
|
||
kwargs = {}
|
||
if 'conflict_strategy' in sig.parameters:
|
||
kwargs['conflict_strategy'] = conflict_strategy
|
||
if 'sync_milestones' in sig.parameters:
|
||
kwargs['sync_milestones'] = sync_milestones
|
||
if 'sync_comments' in sig.parameters:
|
||
kwargs['sync_comments'] = sync_comments
|
||
if 'enable_deletion' in sig.parameters:
|
||
kwargs['enable_deletion'] = enable_deletion
|
||
|
||
# 根据方法名和平台顺序调用相应的双向同步方法
|
||
method_name = bidirectional_method.__name__
|
||
|
||
if method_name == 'bidirectional_sync_gitlink_github':
|
||
# 确定GitLink和GitHub的顺序
|
||
if platform_a == 'gitlink':
|
||
result = bidirectional_method(
|
||
platform_a_org, platform_a_repo, # GitLink
|
||
platform_b_org, platform_b_repo, # GitHub
|
||
**kwargs
|
||
)
|
||
else: # GitHub是平台A
|
||
result = bidirectional_method(
|
||
platform_b_org, platform_b_repo, # GitLink
|
||
platform_a_org, platform_a_repo, # GitHub
|
||
**kwargs
|
||
)
|
||
elif method_name == 'bidirectional_sync_gitlink_gitee':
|
||
# 确定GitLink和Gitee的顺序
|
||
if platform_a == 'gitlink':
|
||
result = bidirectional_method(
|
||
platform_a_org, platform_a_repo, # GitLink
|
||
platform_b_org, platform_b_repo, # Gitee
|
||
**kwargs
|
||
)
|
||
else: # Gitee是平台A
|
||
result = bidirectional_method(
|
||
platform_b_org, platform_b_repo, # GitLink
|
||
platform_a_org, platform_a_repo, # Gitee
|
||
**kwargs
|
||
)
|
||
elif method_name == 'bidirectional_sync_github_gitee':
|
||
# 确定GitHub和Gitee的顺序
|
||
if platform_a == 'github':
|
||
result = bidirectional_method(
|
||
platform_a_org, platform_a_repo, # GitHub
|
||
platform_b_org, platform_b_repo, # Gitee
|
||
**kwargs
|
||
)
|
||
else: # Gitee是平台A
|
||
result = bidirectional_method(
|
||
platform_b_org, platform_b_repo, # GitHub
|
||
platform_a_org, platform_a_repo, # Gitee
|
||
**kwargs
|
||
)
|
||
else:
|
||
print("❌ 未知的双向同步方法: {}".format(method_name))
|
||
return
|
||
|
||
if result and isinstance(result, dict):
|
||
print("✅ 双向同步完成!")
|
||
print("📊 双向同步统计:")
|
||
|
||
# 输出各方向的统计
|
||
for direction_key in result:
|
||
if '_to_' in direction_key and isinstance(result[direction_key], dict):
|
||
direction_stats = result[direction_key]
|
||
direction_name = direction_key.replace('_', ' → ').title()
|
||
print(" 📤 {}:".format(direction_name))
|
||
print(" • 新建: {}".format(direction_stats.get('created', 0)))
|
||
print(" • 更新: {}".format(direction_stats.get('updated', 0)))
|
||
print(" • 跳过: {}".format(direction_stats.get('skipped', 0)))
|
||
print(" • 失败: {}".format(direction_stats.get('failed', 0)))
|
||
|
||
# 输出总体统计
|
||
print(" 🔄 总体统计:")
|
||
print(" • 处理Issue总数: {}".format(result.get('total_processed', 0)))
|
||
print(" • 解决冲突: {}".format(result.get('conflicts_resolved', 0)))
|
||
|
||
# 输出里程碑同步结果
|
||
if result.get('milestone_sync_result'):
|
||
milestone_result = result['milestone_sync_result']
|
||
print(" 🏁 里程碑同步统计:")
|
||
for key, value in milestone_result.items():
|
||
if isinstance(value, dict):
|
||
created_count = sum(v for k, v in value.items() if 'created' in k and isinstance(v, int))
|
||
if created_count > 0:
|
||
direction_name = key.replace('_', ' → ').title()
|
||
print(" • {}: {} 个".format(direction_name, created_count))
|
||
else:
|
||
print("❌ 双向同步失败")
|
||
|
||
except Exception as e:
|
||
print("💥 双向同步任务执行异常: {}".format(str(e)))
|
||
|
||
|
||
@app.post("/webhook")
|
||
async def webhook_endpoint(request: Request):
|
||
"""Webhook接收端点 - 自动同步Gitee和GitLink"""
|
||
try:
|
||
if not DEPENDENCIES_AVAILABLE or not webhook_handler:
|
||
return {
|
||
"success": False,
|
||
"message": "Webhook服务不可用",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
# 获取请求头
|
||
headers = dict(request.headers)
|
||
|
||
# 获取请求体
|
||
webhook_data = await request.json()
|
||
|
||
# 处理webhook
|
||
result = webhook_handler.process_webhook(webhook_data, headers)
|
||
|
||
return result
|
||
|
||
except Exception as e:
|
||
error_msg = f"Webhook处理异常: {str(e)}"
|
||
print(f"❌ {error_msg}")
|
||
return {
|
||
"success": False,
|
||
"message": error_msg,
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
|
||
@app.get("/webhook/status")
|
||
async def webhook_status():
|
||
"""获取Webhook服务状态"""
|
||
return {
|
||
"success": True,
|
||
"data": {
|
||
"webhook_available": DEPENDENCIES_AVAILABLE and webhook_handler is not None,
|
||
"supported_platforms": ["gitee", "gitlink"],
|
||
"repo_config": webhook_handler.repo_config if webhook_handler else None,
|
||
"loop_detection": "启用 (5分钟窗口)" if webhook_handler else "不可用",
|
||
"sync_api_url": webhook_handler.sync_api_url if webhook_handler else None
|
||
},
|
||
"message": "Webhook服务状态获取成功",
|
||
"timestamp": time.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
|
||
|
||
if __name__ == '__main__':
|
||
print("🎯 启动独立的Issue同步服务...")
|
||
print("📖 API文档: http://localhost:8001/docs")
|
||
print("🔍 服务状态: http://localhost:8001/status")
|
||
print("=" * 50)
|
||
|
||
# 修复uvicorn启动配置 - 使用导入字符串
|
||
uvicorn.run(
|
||
"issue_sync_web:app", # 使用导入字符串而不是直接传递app对象
|
||
host='0.0.0.0',
|
||
port=8001,
|
||
reload=True,
|
||
debug=True
|
||
) |