- 新增完整的 Python 实现,替代 Go 版本 - 添加 Web 登录界面和仪表板 - 实现 JWT 认证和 API 密钥管理 - 添加数据库存储功能 - 保持与 Go 版本一致的目录结构和启动脚本 - 包含完整的文档和测试脚本
189 lines
5.8 KiB
Python
189 lines
5.8 KiB
Python
"""
|
|
配置管理模块
|
|
支持环境分发、防抖策略和队列配置
|
|
"""
|
|
|
|
from typing import Dict, List, Optional
|
|
from pydantic import Field, validator
|
|
from pydantic_settings import BaseSettings
|
|
import yaml
|
|
from pathlib import Path
|
|
|
|
|
|
class EnvironmentConfig(BaseSettings):
|
|
"""环境配置"""
|
|
branches: List[str] = Field(default_factory=list)
|
|
jenkins_job: str
|
|
jenkins_url: str
|
|
priority: int = Field(default=1, ge=1, le=10)
|
|
|
|
|
|
class DeduplicationConfig(BaseSettings):
|
|
"""防抖配置"""
|
|
enabled: bool = True
|
|
window_seconds: int = Field(default=300, ge=1) # 5分钟防抖窗口
|
|
strategy: str = Field(default="commit_branch") # commit_hash + branch
|
|
cache_ttl: int = Field(default=3600, ge=1) # 缓存1小时
|
|
|
|
|
|
class QueueConfig(BaseSettings):
|
|
"""队列配置"""
|
|
max_concurrent: int = Field(default=10, ge=1)
|
|
max_retries: int = Field(default=3, ge=0)
|
|
retry_delay: int = Field(default=60, ge=1) # 秒
|
|
priority_levels: int = Field(default=3, ge=1, le=10)
|
|
|
|
|
|
class JenkinsConfig(BaseSettings):
|
|
"""Jenkins 配置"""
|
|
username: str
|
|
token: str
|
|
timeout: int = Field(default=30, ge=1)
|
|
retry_attempts: int = Field(default=3, ge=1)
|
|
|
|
|
|
class DatabaseConfig(BaseSettings):
|
|
"""数据库配置"""
|
|
url: str = Field(default="sqlite:///./webhook_ambassador.db")
|
|
echo: bool = False
|
|
pool_size: int = Field(default=10, ge=1)
|
|
max_overflow: int = Field(default=20, ge=0)
|
|
|
|
|
|
class RedisConfig(BaseSettings):
|
|
"""Redis 配置"""
|
|
url: str = Field(default="redis://localhost:6379/0")
|
|
password: Optional[str] = None
|
|
db: int = Field(default=0, ge=0)
|
|
|
|
|
|
class LoggingConfig(BaseSettings):
|
|
"""日志配置"""
|
|
level: str = Field(default="INFO")
|
|
format: str = Field(default="json")
|
|
file: Optional[str] = None
|
|
|
|
|
|
class SecurityConfig(BaseSettings):
|
|
"""安全配置"""
|
|
secret_key: str
|
|
webhook_secret_header: str = Field(default="X-Gitea-Signature")
|
|
rate_limit_per_minute: int = Field(default=100, ge=1)
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""主配置类"""
|
|
|
|
# 基础配置
|
|
app_name: str = "Gitea Webhook Ambassador"
|
|
version: str = "1.0.0"
|
|
debug: bool = False
|
|
|
|
# 服务器配置
|
|
host: str = "0.0.0.0"
|
|
port: int = Field(default=8000, ge=1, le=65535)
|
|
|
|
# 数据库配置
|
|
database_url: str = Field(default="sqlite:///./webhook_ambassador.db")
|
|
|
|
# Redis 配置
|
|
redis_url: str = Field(default="redis://localhost:6379/0")
|
|
redis_password: str = Field(default="")
|
|
redis_db: int = Field(default=0)
|
|
|
|
# Jenkins 配置
|
|
jenkins_username: str = Field(default="admin")
|
|
jenkins_token: str = Field(default="")
|
|
jenkins_timeout: int = Field(default=30)
|
|
|
|
# 安全配置
|
|
security_secret_key: str = Field(default="")
|
|
security_webhook_secret_header: str = Field(default="X-Gitea-Signature")
|
|
security_rate_limit_per_minute: int = Field(default=100)
|
|
|
|
# 日志配置
|
|
logging_level: str = Field(default="INFO")
|
|
logging_format: str = Field(default="json")
|
|
logging_file: str = Field(default="")
|
|
|
|
# 队列配置
|
|
queue_max_concurrent: int = Field(default=10)
|
|
queue_max_retries: int = Field(default=3)
|
|
queue_retry_delay: int = Field(default=60)
|
|
queue_priority_levels: int = Field(default=3)
|
|
|
|
# 防抖配置
|
|
deduplication_enabled: bool = Field(default=True)
|
|
deduplication_window_seconds: int = Field(default=300)
|
|
deduplication_strategy: str = Field(default="commit_branch")
|
|
deduplication_cache_ttl: int = Field(default=3600)
|
|
|
|
# 业务配置
|
|
environments: Dict[str, EnvironmentConfig] = Field(default_factory=dict)
|
|
deduplication: DeduplicationConfig = DeduplicationConfig()
|
|
queue: QueueConfig = QueueConfig()
|
|
|
|
class Config:
|
|
env_file = ".env"
|
|
env_nested_delimiter = "__"
|
|
|
|
@validator("environments", pre=True)
|
|
def load_environments_from_file(cls, v):
|
|
"""从配置文件加载环境配置"""
|
|
if isinstance(v, dict) and v:
|
|
return v
|
|
|
|
# 尝试从配置文件加载
|
|
config_file = Path("config/environments.yaml")
|
|
if config_file.exists():
|
|
with open(config_file, "r", encoding="utf-8") as f:
|
|
config_data = yaml.safe_load(f)
|
|
return config_data.get("environments", {})
|
|
|
|
# 默认配置
|
|
return {
|
|
"dev": EnvironmentConfig(
|
|
branches=["dev", "develop", "development"],
|
|
jenkins_job="alpha-build",
|
|
jenkins_url="https://jenkins-alpha.example.com",
|
|
priority=2
|
|
),
|
|
"prod": EnvironmentConfig(
|
|
branches=["prod", "production", "main", "master"],
|
|
jenkins_job="production-build",
|
|
jenkins_url="https://jenkins-prod.example.com",
|
|
priority=1
|
|
),
|
|
"default": EnvironmentConfig(
|
|
branches=["*"],
|
|
jenkins_job="default-build",
|
|
jenkins_url="https://jenkins-default.example.com",
|
|
priority=3
|
|
)
|
|
}
|
|
|
|
def get_environment_for_branch(self, branch: str) -> Optional[EnvironmentConfig]:
|
|
"""根据分支名获取对应的环境配置"""
|
|
for env_name, env_config in self.environments.items():
|
|
if branch in env_config.branches or "*" in env_config.branches:
|
|
return env_config
|
|
return None
|
|
|
|
def get_environment_by_name(self, name: str) -> Optional[EnvironmentConfig]:
|
|
"""根据环境名获取配置"""
|
|
return self.environments.get(name)
|
|
|
|
|
|
# 全局配置实例
|
|
settings = Settings()
|
|
|
|
|
|
def get_settings() -> Settings:
|
|
"""获取配置实例"""
|
|
return settings
|
|
|
|
|
|
def reload_settings():
|
|
"""重新加载配置"""
|
|
global settings
|
|
settings = Settings() |