- 新增完整的 Python 实现,替代 Go 版本 - 添加 Web 登录界面和仪表板 - 实现 JWT 认证和 API 密钥管理 - 添加数据库存储功能 - 保持与 Go 版本一致的目录结构和启动脚本 - 包含完整的文档和测试脚本
100 lines
3.8 KiB
Python
100 lines
3.8 KiB
Python
"""
|
|
Jenkins 服务
|
|
提供与 Jenkins 的交互功能
|
|
"""
|
|
|
|
import aiohttp
|
|
import structlog
|
|
from typing import Optional, Dict, Any
|
|
|
|
from app.config import get_settings
|
|
|
|
logger = structlog.get_logger()
|
|
|
|
class JenkinsService:
|
|
"""Jenkins 服务类"""
|
|
|
|
def __init__(self):
|
|
self.settings = get_settings()
|
|
self.base_url = self.settings.jenkins.url
|
|
self.username = self.settings.jenkins.username
|
|
self.token = self.settings.jenkins.token
|
|
self.timeout = self.settings.jenkins.timeout
|
|
|
|
async def test_connection(self) -> bool:
|
|
"""测试 Jenkins 连接"""
|
|
try:
|
|
async with aiohttp.ClientSession() as session:
|
|
auth = aiohttp.BasicAuth(self.username, self.token)
|
|
async with session.get(
|
|
f"{self.base_url}/api/json",
|
|
auth=auth,
|
|
timeout=aiohttp.ClientTimeout(total=self.timeout)
|
|
) as response:
|
|
if response.status == 200:
|
|
logger.info("Jenkins connection test successful")
|
|
return True
|
|
else:
|
|
logger.warning(f"Jenkins connection test failed with status {response.status}")
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"Jenkins connection test failed: {str(e)}")
|
|
return False
|
|
|
|
async def trigger_job(self, job_name: str, parameters: Optional[Dict[str, Any]] = None) -> bool:
|
|
"""触发 Jenkins 任务"""
|
|
try:
|
|
async with aiohttp.ClientSession() as session:
|
|
auth = aiohttp.BasicAuth(self.username, self.token)
|
|
|
|
# 构建请求 URL
|
|
url = f"{self.base_url}/job/{job_name}/build"
|
|
|
|
# 如果有参数,使用参数化构建
|
|
if parameters:
|
|
url = f"{self.base_url}/job/{job_name}/buildWithParameters"
|
|
|
|
async with session.post(
|
|
url,
|
|
auth=auth,
|
|
params=parameters or {},
|
|
timeout=aiohttp.ClientTimeout(total=self.timeout)
|
|
) as response:
|
|
if response.status in [200, 201]:
|
|
logger.info(f"Successfully triggered Jenkins job: {job_name}")
|
|
return True
|
|
else:
|
|
logger.error(f"Failed to trigger Jenkins job {job_name}: {response.status}")
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"Error triggering Jenkins job {job_name}: {str(e)}")
|
|
return False
|
|
|
|
async def get_job_info(self, job_name: str) -> Optional[Dict[str, Any]]:
|
|
"""获取任务信息"""
|
|
try:
|
|
async with aiohttp.ClientSession() as session:
|
|
auth = aiohttp.BasicAuth(self.username, self.token)
|
|
async with session.get(
|
|
f"{self.base_url}/job/{job_name}/api/json",
|
|
auth=auth,
|
|
timeout=aiohttp.ClientTimeout(total=self.timeout)
|
|
) as response:
|
|
if response.status == 200:
|
|
return await response.json()
|
|
else:
|
|
logger.warning(f"Failed to get job info for {job_name}: {response.status}")
|
|
return None
|
|
except Exception as e:
|
|
logger.error(f"Error getting job info for {job_name}: {str(e)}")
|
|
return None
|
|
|
|
# 全局服务实例
|
|
_jenkins_service = None
|
|
|
|
def get_jenkins_service() -> JenkinsService:
|
|
"""获取 Jenkins 服务实例"""
|
|
global _jenkins_service
|
|
if _jenkins_service is None:
|
|
_jenkins_service = JenkinsService()
|
|
return _jenkins_service |