playbook/tests/templates/validate_ci_templates.sh

333 lines
9.8 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env sh
# CI 模板验证脚本
set -eu
echo "========================================"
echo "🔧 CI 模板验证"
echo "========================================"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PLAYBOOK_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
TEMPLATES_DIR="$PLAYBOOK_ROOT/templates/ci"
VALIDATION_PASSED=0
VALIDATION_FAILED=0
ERRORS_FILE="/tmp/ci_template_validation_errors.txt"
REPORT_FILE="$SCRIPT_DIR/ci_validation_report.txt"
> "$ERRORS_FILE"
> "$REPORT_FILE"
echo "📁 模板目录: $TEMPLATES_DIR"
echo ""
# ============================================
# 辅助函数
# ============================================
validate_file_exists() {
local file="$1"
local description="$2"
if [ -f "$file" ]; then
echo "$description: $(basename "$file")"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
return 0
else
echo "$description: $(basename "$file") - 文件不存在"
echo "文件不存在: $file" >> "$ERRORS_FILE"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
return 1
fi
}
validate_yaml_syntax() {
local file="$1"
local description="$2"
if ! command -v yamllint >/dev/null 2>&1; then
echo " ⚠️ $description: 跳过yamllint 未安装)"
return 0
fi
if yamllint -d relaxed "$file" >/dev/null 2>&1; then
echo "$description: YAML 语法正确"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
return 0
else
echo "$description: YAML 语法错误"
echo "YAML 语法错误: $file" >> "$ERRORS_FILE"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
return 1
fi
}
validate_workflow_structure() {
local file="$1"
echo " 📋 检查 workflow 结构:"
# 检查必要字段
if grep -q "^name:" "$file"; then
echo " ✓ 包含 name 字段"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ 缺少 name 字段"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
if grep -q "^on:" "$file"; then
echo " ✓ 包含 on 触发器"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ 缺少 on 触发器"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
if grep -q "^jobs:" "$file"; then
echo " ✓ 包含 jobs 定义"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ 缺少 jobs 定义"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
# 检查 runs-on
if grep -q "runs-on:" "$file"; then
runner=$(grep "runs-on:" "$file" | head -1 | awk '{print $2}')
echo " ✓ 配置了 runner: $runner"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ 缺少 runs-on 配置"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
# 检查 steps
if grep -q "steps:" "$file"; then
step_count=$(grep -c "^ - name:" "$file" || echo 0)
echo " ✓ 包含 $step_count 个步骤"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ 缺少 steps 定义"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
}
# ============================================
# 查找并验证 Gitea workflow 文件
# ============================================
echo "🔍 查找 Gitea workflow 文件"
GITEA_WORKFLOWS_DIR="$TEMPLATES_DIR/gitea/.gitea/workflows"
if [ ! -d "$GITEA_WORKFLOWS_DIR" ]; then
echo "⚠️ Gitea workflows 目录不存在: $GITEA_WORKFLOWS_DIR"
echo "跳过 Gitea workflow 验证"
else
WORKFLOW_FILES=$(find "$GITEA_WORKFLOWS_DIR" -name "*.yml" -o -name "*.yaml" 2>/dev/null || true)
if [ -z "$WORKFLOW_FILES" ]; then
echo "⚠️ 未找到 Gitea workflow 文件"
else
for workflow in $WORKFLOW_FILES; do
echo ""
echo "🔍 验证 $(basename "$workflow")"
if validate_file_exists "$workflow" "$(basename "$workflow")"; then
# 验证 YAML 语法
validate_yaml_syntax "$workflow" "$(basename "$workflow")"
# 验证 workflow 结构
validate_workflow_structure "$workflow"
# 检查是否包含中文注释(符合项目风格)
if grep -q "# .*[\u4e00-\u9fa5]" "$workflow" 2>/dev/null || grep -qP "[\x{4e00}-\x{9fa5}]" "$workflow" 2>/dev/null; then
echo " ✓ 包含中文注释(符合项目风格)"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
# 检查配置区域标记
if grep -q "# ====.*配置.*====" "$workflow"; then
echo " ✓ 包含配置区域标记"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
# 检查环境变量配置
if grep -q "^env:" "$workflow"; then
echo " ✓ 包含环境变量配置"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
fi
done
fi
fi
echo ""
# ============================================
# 查找并验证 GitHub Actions workflow 文件
# ============================================
echo "🔍 查找 GitHub Actions workflow 文件"
GITHUB_WORKFLOWS_DIR="$TEMPLATES_DIR/github/.github/workflows"
if [ -d "$GITHUB_WORKFLOWS_DIR" ]; then
WORKFLOW_FILES=$(find "$GITHUB_WORKFLOWS_DIR" -name "*.yml" -o -name "*.yaml" 2>/dev/null || true)
if [ -n "$WORKFLOW_FILES" ]; then
for workflow in $WORKFLOW_FILES; do
echo ""
echo "🔍 验证 $(basename "$workflow")"
if validate_file_exists "$workflow" "$(basename "$workflow")"; then
# 验证 YAML 语法
validate_yaml_syntax "$workflow" "$(basename "$workflow")"
# 验证 workflow 结构
validate_workflow_structure "$workflow"
fi
done
fi
else
echo " GitHub Actions workflows 目录不存在(可选)"
fi
echo ""
# ============================================
# 验证特定 workflow 模板
# ============================================
echo "🔍 验证特定 workflow 模板"
# 检查 standards-check workflow
STANDARDS_CHECK="$GITEA_WORKFLOWS_DIR/standards-check.yml"
if [ -f "$STANDARDS_CHECK" ]; then
echo ""
echo "📋 验证 standards-check.yml:"
# 检查是否包含格式化检查
if grep -q "格式化\|format" "$STANDARDS_CHECK"; then
echo " ✓ 包含格式化检查"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
# 检查是否包含 lint 检查
if grep -q "lint\|检查" "$STANDARDS_CHECK"; then
echo " ✓ 包含 lint 检查"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
else
echo " 未找到 standards-check.yml可选"
fi
# 检查 test workflow
TEST_WORKFLOW="$GITEA_WORKFLOWS_DIR/test.yml"
if [ -f "$TEST_WORKFLOW" ]; then
echo ""
echo "📋 验证 test.yml:"
# 检查是否包含测试步骤
if grep -q "测试\|test" "$TEST_WORKFLOW"; then
echo " ✓ 包含测试步骤"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
# 检查是否配置了测试矩阵
if grep -q "strategy:" "$TEST_WORKFLOW" && grep -q "matrix:" "$TEST_WORKFLOW"; then
echo " ✓ 配置了测试矩阵"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
else
echo " 未找到 test.yml可选"
fi
echo ""
# ============================================
# 验证 README 文档
# ============================================
echo "🔍 验证 CI 模板文档"
if [ -d "$TEMPLATES_DIR" ]; then
# 查找 README
README_FILE=""
for name in README.md readme.md README README.txt; do
if [ -f "$TEMPLATES_DIR/$name" ]; then
README_FILE="$TEMPLATES_DIR/$name"
break
fi
done
if [ -n "$README_FILE" ]; then
echo " ✅ 找到说明文档: $(basename "$README_FILE")"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
# 检查文档内容
if grep -qi "使用\|usage\|how to" "$README_FILE"; then
echo " ✓ 包含使用说明"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
else
echo " ⚠️ 未找到 README 文档(建议添加)"
fi
fi
echo ""
# ============================================
# 生成验证报告
# ============================================
echo "========================================"
echo "📊 验证结果统计"
echo "========================================"
echo "✅ 通过: $VALIDATION_PASSED"
echo "❌ 失败: $VALIDATION_FAILED"
if [ $((VALIDATION_PASSED + VALIDATION_FAILED)) -gt 0 ]; then
echo "📈 通过率: $(awk "BEGIN {printf \"%.1f\", ($VALIDATION_PASSED * 100.0) / ($VALIDATION_PASSED + $VALIDATION_FAILED)}")%"
else
echo "📈 通过率: N/A (无测试项)"
fi
echo ""
# 写入报告文件
{
echo "CI 模板验证报告"
echo "===================="
echo ""
echo "验证时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "模板目录: $TEMPLATES_DIR"
echo ""
echo "统计结果:"
echo " 通过: $VALIDATION_PASSED"
echo " 失败: $VALIDATION_FAILED"
if [ $((VALIDATION_PASSED + VALIDATION_FAILED)) -gt 0 ]; then
echo " 通过率: $(awk "BEGIN {printf \"%.1f\", ($VALIDATION_PASSED * 100.0) / ($VALIDATION_PASSED + $VALIDATION_FAILED)}")%"
fi
echo ""
if [ -s "$ERRORS_FILE" ]; then
echo "错误详情:"
cat "$ERRORS_FILE"
fi
} > "$REPORT_FILE"
echo "📄 详细报告: $REPORT_FILE"
echo "========================================"
# 清理临时文件
rm -f "$ERRORS_FILE"
# 返回结果
if [ "$VALIDATION_FAILED" -eq 0 ]; then
echo "✅ 所有 CI 模板验证通过"
exit 0
else
echo "❌ CI 模板验证失败 ($VALIDATION_FAILED 个错误)"
exit 1
fi