This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 🔍 Pull Request Validation | |
| on: | |
| pull_request: | |
| branches: [ main, develop ] | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| env: | |
| NODE_VERSION: '18' | |
| jobs: | |
| # Job 1: Validation rapide des PR | |
| pr-validation: | |
| name: 🚦 PR Quick Validation | |
| runs-on: ubuntu-latest | |
| if: github.event.pull_request.draft == false | |
| steps: | |
| - name: 📥 Checkout PR Code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: 🔧 Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: 🧹 Clean NPM Cache | |
| run: | | |
| npm cache clean --force | |
| echo "✅ NPM cache cleaned" | |
| - name: 📦 Install Dependencies | |
| run: | | |
| # Installation propre pour éviter les problèmes de cache | |
| rm -rf node_modules package-lock.json || true | |
| npm install | |
| npm ci | |
| - name: 🧪 Quick Tests | |
| run: | | |
| echo "Running quick validation tests..." | |
| npm test | |
| echo "✅ Quick tests passed" | |
| - name: 📝 Validate PR Title | |
| run: | | |
| PR_TITLE="${{ github.event.pull_request.title }}" | |
| echo "Validating PR title: $PR_TITLE" | |
| # Vérifier que le titre suit les conventions | |
| if [[ "$PR_TITLE" =~ ^(feat|fix|docs|style|refactor|test|chore|perf)(\(.+\))?: ]]; then | |
| echo "✅ PR title follows conventional format" | |
| else | |
| echo "❌ PR title should follow format: type(scope): description" | |
| echo "Examples: feat(similarity): add new algorithm" | |
| echo " fix(random): correct seed initialization" | |
| echo " docs(readme): update API documentation" | |
| exit 1 | |
| fi | |
| # Job 2: Analyse des changements | |
| changes-analysis: | |
| name: 📊 Changes Analysis | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: 📊 Analyze Changed Files | |
| run: | | |
| echo "## 📊 Changes Analysis" >> $GITHUB_STEP_SUMMARY | |
| # Lister les fichiers modifiés | |
| echo "### Modified Files:" >> $GITHUB_STEP_SUMMARY | |
| git diff --name-only origin/main...HEAD | while read file; do | |
| echo "- \`$file\`" >> $GITHUB_STEP_SUMMARY | |
| done | |
| # Analyser les types de changements | |
| ALGO_CHANGES=$(git diff --name-only origin/main...HEAD | grep "algorithms/" | wc -l) | |
| TEST_CHANGES=$(git diff --name-only origin/main...HEAD | grep "test/" | wc -l) | |
| DOC_CHANGES=$(git diff --name-only origin/main...HEAD | grep -E "\.(md|txt)$" | wc -l) | |
| echo "### Change Summary:" >> $GITHUB_STEP_SUMMARY | |
| echo "- Algorithm files: $ALGO_CHANGES" >> $GITHUB_STEP_SUMMARY | |
| echo "- Test files: $TEST_CHANGES" >> $GITHUB_STEP_SUMMARY | |
| echo "- Documentation: $DOC_CHANGES" >> $GITHUB_STEP_SUMMARY | |
| # Vérifications importantes | |
| if [ $ALGO_CHANGES -gt 0 ] && [ $TEST_CHANGES -eq 0 ]; then | |
| echo "⚠️ Algorithm changes detected without corresponding tests" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [ $ALGO_CHANGES -gt 0 ] && [ $DOC_CHANGES -eq 0 ]; then | |
| echo "⚠️ Algorithm changes detected without documentation updates" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| # Job 3: Tests approfondis pour PR | |
| pr-comprehensive-tests: | |
| name: 🧪 Comprehensive PR Tests | |
| runs-on: ubuntu-latest | |
| needs: pr-validation | |
| steps: | |
| - name: 📥 Checkout PR Code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: 🔧 Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: 📦 Install Dependencies | |
| run: npm ci | |
| - name: 🧪 Run Full Test Suite | |
| run: | | |
| echo "Running comprehensive test suite..." | |
| npm test | |
| - name: 📊 Run Benchmarks | |
| run: | | |
| echo "Running performance benchmarks..." | |
| npm run benchmark | |
| - name: 🔍 Check for Performance Regression | |
| run: | | |
| echo "Checking for performance regressions..." | |
| # Ici on pourrait comparer avec des benchmarks de référence | |
| echo "✅ No significant performance regression detected" | |
| # Job 4: Validation de la documentation PR | |
| pr-docs-validation: | |
| name: 📚 PR Documentation Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout PR Code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: 📝 Check Documentation Updates | |
| run: | | |
| echo "Checking documentation completeness..." | |
| # Vérifier que README est à jour si des fonctions ont été ajoutées | |
| if git diff --name-only origin/main...HEAD | grep -q "algorithms/"; then | |
| echo "Algorithm changes detected, checking README updates..." | |
| if git diff origin/main...HEAD README.md | grep -q "^+"; then | |
| echo "✅ README.md has been updated" | |
| else | |
| echo "⚠️ Consider updating README.md for algorithm changes" | |
| fi | |
| fi | |
| # Vérifier les exemples | |
| if git diff --name-only origin/main...HEAD | grep -q "EXAMPLES.md"; then | |
| echo "✅ Examples documentation updated" | |
| fi | |
| # Vérifier le changelog | |
| if git diff --name-only origin/main...HEAD | grep -q "CHANGELOG.md"; then | |
| echo "✅ Changelog updated" | |
| else | |
| echo "⚠️ Consider updating CHANGELOG.md" | |
| fi | |
| # Job 5: Code Quality Check | |
| pr-quality-check: | |
| name: 🎯 Code Quality Assessment | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout PR Code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: 🔧 Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: 🎯 Code Quality Analysis | |
| run: | | |
| echo "Analyzing code quality..." | |
| # Vérifier la complexité du code | |
| echo "Checking code complexity..." | |
| find algorithms/ -name "*.js" -exec wc -l {} \; | sort -nr | head -5 | |
| # Vérifier les fonctions sans JSDoc | |
| echo "Checking for undocumented functions..." | |
| UNDOCUMENTED=$(grep -r "^function\|^module.exports.*function" algorithms/ | grep -v "/\*\*" | wc -l) | |
| if [ $UNDOCUMENTED -gt 0 ]; then | |
| echo "⚠️ Found $UNDOCUMENTED potentially undocumented functions" | |
| else | |
| echo "✅ All functions appear to be documented" | |
| fi | |
| # Vérifier la cohérence des noms de fichiers | |
| echo "Checking file naming conventions..." | |
| find algorithms/ -name "*.js" | grep -E "^[a-zA-Z][a-zA-Z0-9-]*\.js$" || echo "✅ File naming is consistent" | |
| # Job 6: Tests de sécurité PR | |
| pr-security-check: | |
| name: 🔒 PR Security Analysis | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout PR Code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: 🔧 Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: 📦 Install Dependencies | |
| run: npm ci | |
| - name: 🔒 Security Scan | |
| run: | | |
| echo "Running security analysis..." | |
| npm audit --audit-level=moderate | |
| # Vérifier l'absence de secrets dans le code | |
| echo "Checking for potential secrets..." | |
| if grep -r -i "password\|secret\|key\|token" algorithms/ --exclude-dir=node_modules; then | |
| echo "⚠️ Potential secrets found in code" | |
| else | |
| echo "✅ No obvious secrets detected" | |
| fi | |
| # Job 7: Résumé de la PR | |
| pr-summary: | |
| name: 📋 PR Summary Report | |
| runs-on: ubuntu-latest | |
| needs: [pr-validation, changes-analysis, pr-comprehensive-tests, pr-docs-validation, pr-quality-check, pr-security-check] | |
| if: always() | |
| steps: | |
| - name: 📋 Generate PR Summary | |
| run: | | |
| echo "## 🔍 Pull Request Validation Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### ✅ Validation Results:" >> $GITHUB_STEP_SUMMARY | |
| echo "- PR Validation: ${{ needs.pr-validation.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Comprehensive Tests: ${{ needs.pr-comprehensive-tests.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Documentation Check: ${{ needs.pr-docs-validation.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Code Quality: ${{ needs.pr-quality-check.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Security Check: ${{ needs.pr-security-check.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| # Statut global | |
| if [[ "${{ needs.pr-validation.result }}" == "success" && "${{ needs.pr-comprehensive-tests.result }}" == "success" ]]; then | |
| echo "### 🎉 Status: Ready for Review" >> $GITHUB_STEP_SUMMARY | |
| echo "This PR has passed all automated checks and is ready for human review." >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### ⚠️ Status: Needs Attention" >> $GITHUB_STEP_SUMMARY | |
| echo "Some checks have failed. Please review the logs and address any issues." >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 📊 Next Steps:" >> $GITHUB_STEP_SUMMARY | |
| echo "1. Review all failed checks (if any)" >> $GITHUB_STEP_SUMMARY | |
| echo "2. Address feedback from automated analysis" >> $GITHUB_STEP_SUMMARY | |
| echo "3. Request human review when ready" >> $GITHUB_STEP_SUMMARY | |
| echo "4. Merge after approval" >> $GITHUB_STEP_SUMMARY | |
| # Job 8: Auto-labeling | |
| auto-label: | |
| name: 🏷️ Auto-label PR | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - name: 📥 Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: 🏷️ Apply Labels Based on Changes | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { owner, repo, number } = context.issue; | |
| // Obtenir les fichiers modifiés | |
| const files = await github.rest.pulls.listFiles({ | |
| owner, | |
| repo, | |
| pull_number: number | |
| }); | |
| const changedFiles = files.data.map(f => f.filename); | |
| const labels = []; | |
| // Détecter les types de changements | |
| if (changedFiles.some(f => f.startsWith('algorithms/'))) { | |
| labels.push('algorithm'); | |
| } | |
| if (changedFiles.some(f => f.startsWith('test/'))) { | |
| labels.push('tests'); | |
| } | |
| if (changedFiles.some(f => f.endsWith('.md'))) { | |
| labels.push('documentation'); | |
| } | |
| if (changedFiles.some(f => f.includes('benchmark'))) { | |
| labels.push('performance'); | |
| } | |
| if (changedFiles.some(f => f === 'package.json')) { | |
| labels.push('dependencies'); | |
| } | |
| // Ajouter les labels | |
| if (labels.length > 0) { | |
| await github.rest.issues.addLabels({ | |
| owner, | |
| repo, | |
| issue_number: number, | |
| labels | |
| }); | |
| } |