Files
novalon-website/scripts/validate-woodpecker.sh
T
张翔 6797a1ee2d
ci/woodpecker/push/woodpecker Pipeline failed
feat: 添加 Woodpecker CI 本地测试工具
- validate-woodpecker.sh: 全面验证配置文件
- test-step.sh: 单步测试工具,支持 Docker 隔离环境
- README.md: 详细使用文档和最佳实践

这些工具可以在本地验证和测试 CI/CD 配置,避免通过持续提交来测试
2026-03-28 22:24:46 +08:00

254 lines
7.2 KiB
Bash
Executable File
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.
#!/bin/bash
set -e
WOODPECKER_FILE=".woodpecker.yml"
echo "=========================================="
echo "Woodpecker CI 配置本地验证工具"
echo "=========================================="
echo ""
# 检查文件是否存在
if [ ! -f "$WOODPECKER_FILE" ]; then
echo "❌ 错误: $WOODPECKER_FILE 文件不存在"
exit 1
fi
echo "✅ 文件存在: $WOODPECKER_FILE"
echo ""
# 1. YAML 语法检查
echo "1️⃣ YAML 语法检查"
echo "----------------------------------------"
if command -v python3 &> /dev/null; then
if python3 -c "import yaml; yaml.safe_load(open('$WOODPECKER_FILE'))" 2>&1; then
echo "✅ YAML 语法正确"
else
echo "❌ YAML 语法错误"
exit 1
fi
else
echo "⚠️ Python3 未安装,跳过 YAML 语法检查"
fi
echo ""
# 2. 检查必需的字段
echo "2️⃣ 检查必需字段"
echo "----------------------------------------"
python3 << 'PYTHON_SCRIPT'
import yaml
import sys
with open('.woodpecker.yml', 'r') as f:
config = yaml.safe_load(f)
errors = []
warnings = []
# 检查 steps
if 'steps' not in config:
errors.append("缺少 'steps' 字段")
else:
steps = config['steps']
if not steps:
errors.append("'steps' 不能为空")
else:
for step_name, step_config in steps.items():
# 检查 image
if 'image' not in step_config:
errors.append(f"步骤 '{step_name}' 缺少 'image' 字段")
# 检查 commands
if 'commands' not in step_config:
warnings.append(f"步骤 '{step_name}' 没有 'commands' 字段")
# 检查 when 条件
if 'when' in step_config:
when = step_config['when']
if 'branch' in when:
print(f" ✅ 步骤 '{step_name}' 有分支条件: {when['branch']}")
if 'event' in when:
print(f" ✅ 步骤 '{step_name}' 有事件条件: {when['event']}")
# 检查 workspace
if 'workspace' in config:
print(f" ✅ workspace 配置: {config['workspace']}")
# 检查 clone
if 'clone' in config:
print(f" ✅ clone 配置: {config['clone']}")
if errors:
print("\n❌ 错误:")
for error in errors:
print(f" - {error}")
sys.exit(1)
if warnings:
print("\n⚠️ 警告:")
for warning in warnings:
print(f" - {warning}")
print("\n✅ 所有必需字段检查通过")
PYTHON_SCRIPT
if [ $? -ne 0 ]; then
exit 1
fi
echo ""
# 3. 检查镜像是否存在
echo "3️⃣ 检查镜像格式"
echo "----------------------------------------"
python3 << 'PYTHON_SCRIPT'
import yaml
import re
with open('.woodpecker.yml', 'r') as f:
config = yaml.safe_load(f)
steps = config.get('steps', {})
image_pattern = re.compile(r'^[a-z0-9\-_./]+(?::[a-z0-9\-_.]+)?$')
for step_name, step_config in steps.items():
image = step_config.get('image', '')
if image:
# 检查镜像格式
if image.startswith('*'):
# YAML anchor,跳过
print(f" ️ 步骤 '{step_name}' 使用 YAML anchor: {image}")
elif image_pattern.match(image):
print(f" ✅ 步骤 '{step_name}' 镜像格式正确: {image}")
else:
print(f" ⚠️ 步骤 '{step_name}' 镜像格式可能有问题: {image}")
print("\n✅ 镜像格式检查完成")
PYTHON_SCRIPT
echo ""
# 4. 检查环境变量和 secrets
echo "4️⃣ 检查环境变量和 secrets"
echo "----------------------------------------"
python3 << 'PYTHON_SCRIPT'
import yaml
with open('.woodpecker.yml', 'r') as f:
config = yaml.safe_load(f)
steps = config.get('steps', {})
secrets_used = set()
for step_name, step_config in steps.items():
env = step_config.get('environment', {})
if isinstance(env, dict):
for key, value in env.items():
if isinstance(value, dict) and 'from_secret' in value:
secret_name = value['from_secret']
secrets_used.add(secret_name)
print(f" 🔐 步骤 '{step_name}' 使用 secret: {secret_name}")
if secrets_used:
print(f"\n📋 需要配置的 secrets:")
for secret in sorted(secrets_used):
print(f" - {secret}")
print("\n⚠️ 请确保在 Woodpecker CI 中配置了这些 secrets")
else:
print(" ️ 没有使用 secrets")
print("\n✅ 环境变量检查完成")
PYTHON_SCRIPT
echo ""
# 5. 检查 when 条件的逻辑
echo "5️⃣ 检查 when 条件逻辑"
echo "----------------------------------------"
python3 << 'PYTHON_SCRIPT'
import yaml
with open('.woodpecker.yml', 'r') as f:
config = yaml.safe_load(f)
steps = config.get('steps', {})
steps_with_conditions = []
steps_without_conditions = []
for step_name, step_config in steps.items():
if 'when' in step_config:
steps_with_conditions.append(step_name)
else:
steps_without_conditions.append(step_name)
if steps_with_conditions:
print(f" ✅ 有条件执行的步骤 ({len(steps_with_conditions)}):")
for step in steps_with_conditions:
print(f" - {step}")
if steps_without_conditions:
print(f"\n ⚠️ 无条件执行的步骤 ({len(steps_without_conditions)}):")
for step in steps_without_conditions:
print(f" - {step}")
print("\n 💡 建议: 大部分步骤应该有 when 条件,避免不必要的执行")
print("\n✅ when 条件检查完成")
PYTHON_SCRIPT
echo ""
# 6. 模拟执行顺序
echo "6️⃣ 模拟执行顺序"
echo "----------------------------------------"
python3 << 'PYTHON_SCRIPT'
import yaml
with open('.woodpecker.yml', 'r') as f:
config = yaml.safe_load(f)
steps = config.get('steps', {})
print(" 📋 步骤执行顺序:")
for i, (step_name, step_config) in enumerate(steps.items(), 1):
image = step_config.get('image', 'N/A')
when = step_config.get('when', {})
conditions = []
if 'branch' in when:
branches = when['branch']
if isinstance(branches, list):
conditions.append(f"branch: {', '.join(branches)}")
else:
conditions.append(f"branch: {branches}")
if 'event' in when:
events = when['event']
if isinstance(events, list):
conditions.append(f"event: {', '.join(events)}")
else:
conditions.append(f"event: {events}")
if 'status' in when:
statuses = when['status']
if isinstance(statuses, list):
conditions.append(f"status: {', '.join(statuses)}")
else:
conditions.append(f"status: {statuses}")
condition_str = f" [{', '.join(conditions)}]" if conditions else ""
print(f" {i}. {step_name}{condition_str}")
print(f" 镜像: {image}")
print("\n✅ 执行顺序分析完成")
PYTHON_SCRIPT
echo ""
echo "=========================================="
echo "✅ 所有检查完成!"
echo "=========================================="
echo ""
echo "💡 提示:"
echo " - 如果所有检查都通过,配置文件基本正确"
echo " - 建议使用 Woodpecker CLI 进行本地测试:"
echo " woodpecker-cli exec .woodpecker.yml"
echo " - 或者使用 Docker:"
echo " docker run --rm -v \$(pwd):/woodpecker/src -w /woodpecker/src woodpeckerci/woodpecker-cli:latest exec .woodpecker.yml"
echo ""