🤖 feat: implement trunk-based CI/CD with local testing
- Designed trunk-based development workflow with branch protection - Added workflow validation job to prevent main branch breaks - Integrated act (GitHub Actions runner) for local Gitea workflow testing - Created unified CI/CD script interface (scripts/cicd.sh) - Added YAML lint configuration with practical limits (400 chars) - Organized all CI/CD scripts under scripts/cicd/ directory - Confirmed Gitea/GitHub Actions compatibility via local testing - Updated ADR 0017 with implementation details and test results - Enhanced documentation with local development workflow See ADR-0017 for complete trunk-based development workflow documentation. See ADR-0016 for CI/CD pipeline design.
This commit is contained in:
174
scripts/validate-cicd-comprehensive.sh
Executable file
174
scripts/validate-cicd-comprehensive.sh
Executable file
@@ -0,0 +1,174 @@
|
||||
#!/bin/bash
|
||||
# Comprehensive CI/CD validation script
|
||||
# Validates workflow without requiring Docker for basic checks
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔍 Comprehensive CI/CD Validation"
|
||||
echo "==================================="
|
||||
|
||||
# 1. Check workflow file exists
|
||||
if [ ! -f ".gitea/workflows/ci-cd.yaml" ]; then
|
||||
echo "❌ Workflow file not found: .gitea/workflows/ci-cd.yaml"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Workflow file found"
|
||||
|
||||
# 2. Validate YAML syntax with Python (no Docker required)
|
||||
echo ""
|
||||
echo "🔍 Validating YAML syntax..."
|
||||
python3 -c "import yaml; yaml.safe_load(open('.gitea/workflows/ci-cd.yaml'))" 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ YAML syntax is valid"
|
||||
else
|
||||
echo "❌ YAML syntax error"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3. Check required fields using Python
|
||||
echo ""
|
||||
echo "📋 Checking required fields..."
|
||||
python3 << 'PYTHON'
|
||||
import yaml
|
||||
|
||||
try:
|
||||
with open('.gitea/workflows/ci-cd.yaml') as f:
|
||||
workflow = yaml.safe_load(f)
|
||||
|
||||
if not workflow:
|
||||
print("❌ Workflow is empty or invalid")
|
||||
exit(1)
|
||||
|
||||
# Check for required fields
|
||||
has_name = 'name' in workflow
|
||||
has_on = 'on' in workflow
|
||||
has_jobs = 'jobs' in workflow
|
||||
|
||||
if not has_name:
|
||||
print("❌ Missing 'name' field")
|
||||
exit(1)
|
||||
|
||||
if not has_on:
|
||||
print("❌ Missing 'on' field")
|
||||
exit(1)
|
||||
|
||||
if not has_jobs:
|
||||
print("❌ Missing 'jobs' field")
|
||||
exit(1)
|
||||
|
||||
print("✅ All required fields present")
|
||||
|
||||
# Check jobs structure
|
||||
jobs = workflow['jobs']
|
||||
print(f"📋 Jobs defined: {', '.join(jobs.keys())}")
|
||||
|
||||
for job_name, job_config in jobs.items():
|
||||
if not isinstance(job_config, dict):
|
||||
print(f"❌ Job '{job_name}' is not properly formatted")
|
||||
exit(1)
|
||||
|
||||
if 'steps' not in job_config:
|
||||
print(f"❌ Job '{job_name}' has no steps")
|
||||
exit(1)
|
||||
|
||||
steps = job_config['steps']
|
||||
if not isinstance(steps, list):
|
||||
print(f"❌ Job '{job_name}' steps are not a list")
|
||||
exit(1)
|
||||
|
||||
steps_count = len(steps)
|
||||
print(f" ✅ {job_name}: {steps_count} steps")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error parsing workflow: {e}")
|
||||
exit(1)
|
||||
PYTHON
|
||||
|
||||
# 4. Check Arcodange-specific configurations
|
||||
echo ""
|
||||
echo "🔧 Checking Arcodange configurations..."
|
||||
python3 << 'PYTHON'
|
||||
import yaml
|
||||
|
||||
with open('.gitea/workflows/ci-cd.yaml') as f:
|
||||
workflow = yaml.safe_load(f)
|
||||
|
||||
# Check environment variables
|
||||
if 'env' in workflow:
|
||||
env_vars = workflow['env']
|
||||
|
||||
gitea_internal = env_vars.get('GITEA_INTERNAL', '')
|
||||
gitea_external = env_vars.get('GITEA_EXTERNAL', '')
|
||||
|
||||
if gitea_internal and 'arcodange.lab' in gitea_internal:
|
||||
print("✅ Arcodange internal URL configured")
|
||||
else:
|
||||
print("⚠️ Arcodange internal URL not found or incorrect")
|
||||
|
||||
if gitea_external and 'arcodange.fr' in gitea_external:
|
||||
print("✅ Arcodange external URL configured")
|
||||
else:
|
||||
print("⚠️ Arcodange external URL not found or incorrect")
|
||||
else:
|
||||
print("⚠️ No environment variables configured")
|
||||
|
||||
# Check concurrency
|
||||
if 'concurrency' in workflow:
|
||||
print("✅ Concurrency control configured")
|
||||
else:
|
||||
print("⚠️ No concurrency control (consider adding)")
|
||||
PYTHON
|
||||
|
||||
# 5. Check workflow structure
|
||||
echo ""
|
||||
echo "🏗️ Checking workflow structure..."
|
||||
python3 << 'PYTHON'
|
||||
import yaml
|
||||
|
||||
with open('.gitea/workflows/ci-cd.yaml') as f:
|
||||
workflow = yaml.safe_load(f)
|
||||
|
||||
# Check triggers
|
||||
if 'on' in workflow:
|
||||
triggers = workflow['on']
|
||||
has_push = 'push' in triggers if isinstance(triggers, dict) else any('push' in str(t) for t in triggers)
|
||||
has_workflow_dispatch = 'workflow_dispatch' in triggers if isinstance(triggers, dict) else any('workflow_dispatch' in str(t) for t in triggers)
|
||||
|
||||
if has_push:
|
||||
print("✅ Push trigger configured")
|
||||
else:
|
||||
print("⚠️ No push trigger")
|
||||
|
||||
if has_workflow_dispatch:
|
||||
print("✅ Manual trigger (workflow_dispatch) configured")
|
||||
else:
|
||||
print("⚠️ No manual trigger")
|
||||
|
||||
# Check paths-ignore
|
||||
if 'on' in workflow and isinstance(workflow['on'], dict) and 'push' in workflow['on']:
|
||||
push_config = workflow['on']['push']
|
||||
if isinstance(push_config, dict) and 'paths-ignore' in push_config:
|
||||
ignored_paths = push_config['paths-ignore']
|
||||
print(f"✅ Paths ignored: {', '.join(ignored_paths)}")
|
||||
else:
|
||||
print("⚠️ No paths-ignore configured")
|
||||
PYTHON
|
||||
|
||||
# 6. Summary
|
||||
echo ""
|
||||
echo "🎉 Validation Complete!"
|
||||
echo "================================"
|
||||
echo "📁 Workflow: .gitea/workflows/ci-cd.yaml"
|
||||
echo "✅ YAML syntax valid"
|
||||
echo "✅ Required fields present"
|
||||
echo "✅ Jobs structure valid"
|
||||
echo "✅ Arcodange configurations checked"
|
||||
echo "🎯 Ready for deployment"
|
||||
|
||||
echo ""
|
||||
echo "💡 Next Steps:"
|
||||
echo " 1. Test with Docker: ./scripts/test-cicd-simple.sh"
|
||||
echo " 2. Commit changes: git commit -m '🤖 ci: validate workflow'"
|
||||
echo " 3. Push to trigger: git push origin main"
|
||||
echo " 4. Monitor pipeline: https://gitea.arcodange.lab/arcodange/DanceLessonsCoach/actions"
|
||||
Reference in New Issue
Block a user