#!/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