Files
tsl-devkit/tests/templates/validate_ci_templates.sh
T
csh ac794a6a70 Squashed 'docs/standards/playbook/' changes from e504a68..b529012
b529012  test(tests): avoid hardcoded missing path
07583c8 🐛 fix(tests): make doc link check awk-portable
6244aa3 🔧 chore(ci): relax gitattributes check
31dd0c5 🐛 fix(scripts): require existing project root
15d4d63 🔧 chore(ci): install python3-pip
90c6313 🔧 chore(ci): run tests in a single job
d84eff0 🔧 chore(ci): make actions base url configurable
395598d 🔧 chore(ci): fix yaml step names
4ae2733  feat(sync_standards): auto-detect existing languages
e97fb00  feat(sync_standards): default gitattributes to append
da0ef2b  test: add automated tests and ci workflow
99bef30 🎨 style(markdown): format all markdown files with prettier
7e96bc8 ♻️ refactor(tsl): split function.md into 44 modular files
0d6b2a0 📝 docs(readme): add quick decision table and TL;DR for distribution methods
3b2188f 🎨 style(markdown): format markdown files with prettier
41fc43b 📝 docs(tsl): document {Unit.}Type source annotation
3dceaf7 📝 docs(tsl): clarify tsf-only top-level rules and type annotations
3a63829 📝 docs(skills): add create-plan skill
f02a707 🐛 fix(scripts): escape markdown backticks in vendor_playbook
064aa92 🐛 fix(scripts): correct bat scripts
4881feb 🔧 chore(gitattributes): enforce crlf for bat files
1fa3e2a 🐛 fix(scripts): escape parentheses in sync_standards output
3958cad 📝 docs(vendor_playbook): mention ci templates
9d059cf  feat(templates): add gitea ci example
a52bb24 📝 docs(codex_skills): normalize markdown formatting
cc8ad4c 📝 docs(skills): slim commit-message
2a98e15 🐛 fix(skills): quote YAML descriptions
8f78d22 🐛 fix(sync_standards): generate minimal AGENTS.md
5547665  feat(skills): add commit-message suggestion skill
3fe8bd7 🔧 chore(sync_standards): create AGENTS.md on sync
283d311  feat(playbook): add syntax book and codex skills tooling
5b97ed5 📝 docs(tsl): clarify syntax references
27e0700  feat(skills): add pdf/docx/pptx/xlsx wrapper workflows
5551363  feat(skills): add debugging and bulk refactor workflows
1d4f548  feat(skills): add built-in workflow skills
c0895dd 📝 docs(skills): add anthropics document-skills integration
cf9f80d 🔧 chore(playbook): add Claude Code skills guide and align python templates

git-subtree-dir: docs/standards/playbook
git-subtree-split: b529012c59c5d67c3073884d7b617763647417fd
2026-01-08 15:56:36 +08:00

333 lines
9.8 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
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