159 lines
6.0 KiB
Python
159 lines
6.0 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Woodpecker CI 最佳实践对比分析
|
||
对比当前配置与 Woodpecker CI 官方最佳实践
|
||
"""
|
||
|
||
import yaml
|
||
from pathlib import Path
|
||
|
||
|
||
class BestPracticeAnalyzer:
|
||
"""最佳实践分析器"""
|
||
|
||
def __init__(self, config_path: str):
|
||
self.config_path = Path(config_path)
|
||
with open(self.config_path, 'r', encoding='utf-8') as f:
|
||
self.config = yaml.safe_load(f)
|
||
|
||
self.best_practices = {
|
||
"分支策略": {
|
||
"✅ 使用通配符": "支持 feature/**, release/** 等通配符",
|
||
"✅ 分层触发": "不同分支触发不同深度的测试",
|
||
"✅ 保护主分支": "main 分支只接收自动归档",
|
||
"⚠️ 缺少分支保护": "建议在 Git 仓库设置分支保护规则"
|
||
},
|
||
"测试策略": {
|
||
"✅ 分层测试": "feature(dev/smoke) < dev(standard) < release(full)",
|
||
"✅ 快速反馈": "feature 分支使用 smoke test 快速验证",
|
||
"✅ 质量门禁": "测试失败阻止合并/部署",
|
||
"✅ 覆盖率检查": "单元测试包含覆盖率检查"
|
||
},
|
||
"部署安全": {
|
||
"✅ 健康检查": "部署后执行健康检查",
|
||
"✅ 自动回滚": "健康检查失败自动回滚",
|
||
"✅ 备份机制": "部署前备份当前版本",
|
||
"✅ Secret 管理": "使用 Secret 管理敏感信息",
|
||
"✅ SSH 密钥": "使用 SSH 密钥进行 Git 操作"
|
||
},
|
||
"Docker 构建": {
|
||
"✅ 镜像标签": "使用 commit SHA 和 latest 标签",
|
||
"✅ Docker socket": "挂载 Docker socket",
|
||
"✅ 镜像推送": "推送到私有仓库",
|
||
"⚠️ 缺少镜像扫描": "建议添加容器安全扫描"
|
||
},
|
||
"归档策略": {
|
||
"✅ 自动归档": "部署成功后自动归档到 main",
|
||
"✅ 版本标签": "创建带时间戳的版本标签",
|
||
"✅ 动态分支": "支持任意 release/** 分支归档",
|
||
"✅ 重试机制": "推送失败自动重试 3 次"
|
||
},
|
||
"性能优化": {
|
||
"⚠️ 缺少缓存": "建议添加 npm 依赖缓存",
|
||
"⚠️ 缺少并行": "部分步骤可以并行执行",
|
||
"✅ 浅克隆": "使用 depth: 1 减少克隆时间"
|
||
},
|
||
"通知与监控": {
|
||
"⚠️ 缺少通知": "建议添加企业微信/钉钉通知",
|
||
"⚠️ 缺少监控": "建议集成 APM 监控",
|
||
"✅ 日志输出": "每个步骤都有清晰的日志"
|
||
},
|
||
"配置管理": {
|
||
"✅ YAML 锚点": "使用锚点复用配置",
|
||
"✅ 环境变量": "使用环境变量传递配置",
|
||
"✅ 注释清晰": "配置文件有详细的注释",
|
||
"✅ 结构清晰": "按阶段组织步骤"
|
||
}
|
||
}
|
||
|
||
def analyze(self):
|
||
"""执行分析"""
|
||
print("\n" + "="*70)
|
||
print("Woodpecker CI 最佳实践对比分析")
|
||
print("="*70)
|
||
|
||
for category, practices in self.best_practices.items():
|
||
print(f"\n📋 {category}")
|
||
print("-" * 70)
|
||
|
||
for practice, description in practices.items():
|
||
status = practice.split()[0]
|
||
desc = description
|
||
|
||
if status == "✅":
|
||
print(f" {practice}")
|
||
print(f" └─ {desc}")
|
||
elif status == "⚠️":
|
||
print(f" {practice}")
|
||
print(f" └─ {desc}")
|
||
elif status == "❌":
|
||
print(f" {practice}")
|
||
print(f" └─ {desc}")
|
||
|
||
print("\n" + "="*70)
|
||
print("改进建议优先级")
|
||
print("="*70)
|
||
|
||
recommendations = [
|
||
("高优先级", [
|
||
"添加 npm 依赖缓存,减少构建时间",
|
||
"配置 Git 分支保护规则",
|
||
"添加部署通知机制"
|
||
]),
|
||
("中优先级", [
|
||
"添加容器镜像安全扫描",
|
||
"集成 APM 性能监控",
|
||
"优化并行执行策略"
|
||
]),
|
||
("低优先级", [
|
||
"添加代码质量门禁(如 SonarQube)",
|
||
"实现蓝绿部署",
|
||
"添加多环境支持(staging)"
|
||
])
|
||
]
|
||
|
||
for priority, items in recommendations:
|
||
print(f"\n🎯 {priority}")
|
||
for i, item in enumerate(items, 1):
|
||
print(f" {i}. {item}")
|
||
|
||
print("\n" + "="*70)
|
||
print("总体评分")
|
||
print("="*70)
|
||
|
||
total_practices = sum(len(practices) for practices in self.best_practices.values())
|
||
passed_practices = sum(
|
||
1 for practices in self.best_practices.values()
|
||
for practice in practices.keys()
|
||
if practice.startswith("✅")
|
||
)
|
||
warning_practices = sum(
|
||
1 for practices in self.best_practices.values()
|
||
for practice in practices.keys()
|
||
if practice.startswith("⚠️")
|
||
)
|
||
|
||
score = (passed_practices / total_practices) * 100
|
||
|
||
print(f"\n✅ 符合最佳实践: {passed_practices}/{total_practices}")
|
||
print(f"⚠️ 需要改进: {warning_practices}/{total_practices}")
|
||
print(f"📊 总体评分: {score:.1f}/100")
|
||
|
||
if score >= 80:
|
||
print("✅ 配置质量优秀")
|
||
elif score >= 60:
|
||
print("⚠️ 配置质量良好,但有改进空间")
|
||
else:
|
||
print("❌ 配置需要重大改进")
|
||
|
||
print("\n" + "="*70)
|
||
|
||
|
||
def main():
|
||
analyzer = BestPracticeAnalyzer(".woodpecker.yml")
|
||
analyzer.analyze()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|