mirror of
https://github.com/zhinianboke/xianyu-auto-reply.git
synced 2025-08-02 04:27:36 +08:00
332 lines
9.6 KiB
Python
332 lines
9.6 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Docker部署配置验证脚本
|
||
检查Docker部署是否包含所有必要的组件和配置
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import yaml
|
||
import json
|
||
from pathlib import Path
|
||
|
||
def check_file_exists(file_path, description):
|
||
"""检查文件是否存在"""
|
||
if os.path.exists(file_path):
|
||
print(f" ✅ {description}: {file_path}")
|
||
return True
|
||
else:
|
||
print(f" ❌ {description}: {file_path} (缺失)")
|
||
return False
|
||
|
||
def check_requirements_txt():
|
||
"""检查requirements.txt中的依赖"""
|
||
print("📦 检查Python依赖...")
|
||
|
||
if not check_file_exists("requirements.txt", "依赖文件"):
|
||
return False
|
||
|
||
required_packages = [
|
||
"fastapi",
|
||
"uvicorn",
|
||
"pydantic",
|
||
"loguru",
|
||
"websockets",
|
||
"aiohttp",
|
||
"PyYAML",
|
||
"PyExecJS",
|
||
"blackboxprotobuf",
|
||
"psutil",
|
||
"requests",
|
||
"python-multipart",
|
||
"openai",
|
||
"python-dotenv"
|
||
]
|
||
|
||
try:
|
||
with open("requirements.txt", "r", encoding="utf-8") as f:
|
||
content = f.read()
|
||
|
||
missing_packages = []
|
||
for package in required_packages:
|
||
if package.lower() not in content.lower():
|
||
missing_packages.append(package)
|
||
|
||
if missing_packages:
|
||
print(f" ❌ 缺失依赖: {', '.join(missing_packages)}")
|
||
return False
|
||
else:
|
||
print(f" ✅ 所有必要依赖都已包含 ({len(required_packages)} 个)")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f" ❌ 读取requirements.txt失败: {e}")
|
||
return False
|
||
|
||
def check_dockerfile():
|
||
"""检查Dockerfile配置"""
|
||
print("\n🐳 检查Dockerfile...")
|
||
|
||
if not check_file_exists("Dockerfile", "Docker镜像文件"):
|
||
return False
|
||
|
||
try:
|
||
with open("Dockerfile", "r", encoding="utf-8") as f:
|
||
content = f.read()
|
||
|
||
required_elements = [
|
||
("FROM python:", "Python基础镜像"),
|
||
("WORKDIR", "工作目录设置"),
|
||
("COPY requirements.txt", "依赖文件复制"),
|
||
("RUN pip install", "依赖安装"),
|
||
("EXPOSE", "端口暴露"),
|
||
("CMD", "启动命令")
|
||
]
|
||
|
||
missing_elements = []
|
||
for element, description in required_elements:
|
||
if element not in content:
|
||
missing_elements.append(description)
|
||
|
||
if missing_elements:
|
||
print(f" ❌ 缺失配置: {', '.join(missing_elements)}")
|
||
return False
|
||
else:
|
||
print(f" ✅ Dockerfile配置完整")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f" ❌ 读取Dockerfile失败: {e}")
|
||
return False
|
||
|
||
def check_docker_compose():
|
||
"""检查docker-compose.yml配置"""
|
||
print("\n🔧 检查Docker Compose配置...")
|
||
|
||
if not check_file_exists("docker-compose.yml", "Docker Compose文件"):
|
||
return False
|
||
|
||
try:
|
||
with open("docker-compose.yml", "r", encoding="utf-8") as f:
|
||
compose_config = yaml.safe_load(f)
|
||
|
||
# 检查服务配置
|
||
if "services" not in compose_config:
|
||
print(" ❌ 缺失services配置")
|
||
return False
|
||
|
||
services = compose_config["services"]
|
||
if "xianyu-app" not in services:
|
||
print(" ❌ 缺失xianyu-app服务")
|
||
return False
|
||
|
||
app_service = services["xianyu-app"]
|
||
|
||
# 检查必要配置
|
||
required_configs = [
|
||
("ports", "端口映射"),
|
||
("volumes", "数据挂载"),
|
||
("environment", "环境变量"),
|
||
("healthcheck", "健康检查")
|
||
]
|
||
|
||
missing_configs = []
|
||
for config, description in required_configs:
|
||
if config not in app_service:
|
||
missing_configs.append(description)
|
||
|
||
if missing_configs:
|
||
print(f" ❌ 缺失配置: {', '.join(missing_configs)}")
|
||
return False
|
||
|
||
# 检查AI相关环境变量
|
||
env_vars = app_service.get("environment", [])
|
||
ai_env_vars = [
|
||
"AI_REPLY_ENABLED",
|
||
"DEFAULT_AI_MODEL",
|
||
"DEFAULT_AI_BASE_URL",
|
||
"AI_REQUEST_TIMEOUT"
|
||
]
|
||
|
||
missing_ai_vars = []
|
||
env_str = str(env_vars)
|
||
for var in ai_env_vars:
|
||
if var not in env_str:
|
||
missing_ai_vars.append(var)
|
||
|
||
if missing_ai_vars:
|
||
print(f" ⚠️ 缺失AI环境变量: {', '.join(missing_ai_vars)}")
|
||
else:
|
||
print(f" ✅ AI环境变量配置完整")
|
||
|
||
print(f" ✅ Docker Compose配置完整")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f" ❌ 读取docker-compose.yml失败: {e}")
|
||
return False
|
||
|
||
def check_env_example():
|
||
"""检查.env.example配置"""
|
||
print("\n⚙️ 检查环境变量模板...")
|
||
|
||
if not check_file_exists(".env.example", "环境变量模板"):
|
||
return False
|
||
|
||
try:
|
||
with open(".env.example", "r", encoding="utf-8") as f:
|
||
content = f.read()
|
||
|
||
# 检查AI相关配置
|
||
ai_configs = [
|
||
"AI_REPLY_ENABLED",
|
||
"DEFAULT_AI_MODEL",
|
||
"DEFAULT_AI_BASE_URL",
|
||
"AI_REQUEST_TIMEOUT",
|
||
"AI_MAX_TOKENS"
|
||
]
|
||
|
||
missing_configs = []
|
||
for config in ai_configs:
|
||
if config not in content:
|
||
missing_configs.append(config)
|
||
|
||
if missing_configs:
|
||
print(f" ❌ 缺失AI配置: {', '.join(missing_configs)}")
|
||
return False
|
||
else:
|
||
print(f" ✅ AI配置完整")
|
||
|
||
# 检查基础配置
|
||
basic_configs = [
|
||
"ADMIN_USERNAME",
|
||
"ADMIN_PASSWORD",
|
||
"JWT_SECRET_KEY",
|
||
"AUTO_REPLY_ENABLED",
|
||
"AUTO_DELIVERY_ENABLED"
|
||
]
|
||
|
||
missing_basic = []
|
||
for config in basic_configs:
|
||
if config not in content:
|
||
missing_basic.append(config)
|
||
|
||
if missing_basic:
|
||
print(f" ❌ 缺失基础配置: {', '.join(missing_basic)}")
|
||
return False
|
||
else:
|
||
print(f" ✅ 基础配置完整")
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f" ❌ 读取.env.example失败: {e}")
|
||
return False
|
||
|
||
def check_documentation():
|
||
"""检查部署文档"""
|
||
print("\n📚 检查部署文档...")
|
||
|
||
docs = [
|
||
("Docker部署说明.md", "Docker部署说明"),
|
||
("README.md", "项目说明文档")
|
||
]
|
||
|
||
all_exist = True
|
||
for doc_file, description in docs:
|
||
if not check_file_exists(doc_file, description):
|
||
all_exist = False
|
||
|
||
return all_exist
|
||
|
||
def check_directory_structure():
|
||
"""检查目录结构"""
|
||
print("\n📁 检查目录结构...")
|
||
|
||
required_dirs = [
|
||
("static", "静态文件目录"),
|
||
("templates", "模板目录(如果存在)")
|
||
]
|
||
|
||
required_files = [
|
||
("Start.py", "主程序文件"),
|
||
("db_manager.py", "数据库管理"),
|
||
("XianyuAutoAsync.py", "闲鱼自动化"),
|
||
("ai_reply_engine.py", "AI回复引擎"),
|
||
("global_config.yml", "全局配置")
|
||
]
|
||
|
||
all_exist = True
|
||
|
||
# 检查目录
|
||
for dir_name, description in required_dirs:
|
||
if os.path.exists(dir_name) and os.path.isdir(dir_name):
|
||
print(f" ✅ {description}: {dir_name}")
|
||
else:
|
||
if dir_name == "templates": # templates是可选的
|
||
print(f" ⚠️ {description}: {dir_name} (可选)")
|
||
else:
|
||
print(f" ❌ {description}: {dir_name} (缺失)")
|
||
all_exist = False
|
||
|
||
# 检查文件
|
||
for file_name, description in required_files:
|
||
if not check_file_exists(file_name, description):
|
||
all_exist = False
|
||
|
||
return all_exist
|
||
|
||
def main():
|
||
"""主检查函数"""
|
||
print("🚀 Docker部署配置验证")
|
||
print("=" * 50)
|
||
|
||
checks = [
|
||
("Python依赖", check_requirements_txt),
|
||
("Dockerfile", check_dockerfile),
|
||
("Docker Compose", check_docker_compose),
|
||
("环境变量", check_env_example),
|
||
("目录结构", check_directory_structure),
|
||
("文档", check_documentation)
|
||
]
|
||
|
||
results = []
|
||
for check_name, check_func in checks:
|
||
try:
|
||
result = check_func()
|
||
results.append((check_name, result))
|
||
except Exception as e:
|
||
print(f" ❌ {check_name}检查异常: {e}")
|
||
results.append((check_name, False))
|
||
|
||
# 总结结果
|
||
print("\n" + "=" * 50)
|
||
print("📊 检查结果总结")
|
||
|
||
passed = 0
|
||
total = len(results)
|
||
|
||
for check_name, result in results:
|
||
status = "✅ 通过" if result else "❌ 失败"
|
||
print(f" {check_name}: {status}")
|
||
if result:
|
||
passed += 1
|
||
|
||
print(f"\n📈 总体评分: {passed}/{total} ({passed/total*100:.1f}%)")
|
||
|
||
if passed == total:
|
||
print("\n🎉 所有检查通过!Docker部署配置完整!")
|
||
print("\n🚀 可以直接使用以下命令部署:")
|
||
print(" docker-compose up -d")
|
||
elif passed >= total * 0.8:
|
||
print("\n⚠️ 大部分检查通过,有少量问题需要修复")
|
||
print(" 建议修复上述问题后再部署")
|
||
else:
|
||
print("\n❌ 多项检查失败,需要完善配置后再部署")
|
||
|
||
return passed == total
|
||
|
||
if __name__ == "__main__":
|
||
success = main()
|
||
sys.exit(0 if success else 1)
|