diff --git a/README.md b/README.md index 2976a92..b41b593 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,10 @@ Review Buddy automates the boring parts of Code Review: * **PR Title**: Renames your PR to follow Conventional Commits (e.g., `fix: login bug` instead of `update`). * **Description**: Writes a full, formatted description (Summary, Changes, Testing Guide) if you didn't provides one. * **Labels**: Automatically adds relevant labels based on change type, quality score, and detected issues. -3. **Engaging Feedback**: comments on your PR in your chosen tone (Professional or Roast). -4. **Final Recommendation**: Provides a clear recommendation (Approve/Request Changes/Reject) with actionable next steps for reviewers. -5. **Interactive Chat**: Reply to any comment with `/Buddy` (e.g., "Why is this wrong? /Buddy") and Review Buddy will explain! +3. **Best Practices Suggestions**: Identifies code patterns that can be improved with modern best practices (e.g., `if (a == undefined)` → `if (!a)`, using `const/let` instead of `var`, arrow functions, template literals, etc.) with before/after examples. +4. **Engaging Feedback**: comments on your PR in your chosen tone (Professional or Roast). +5. **Final Recommendation**: Provides a clear recommendation (Approve/Request Changes/Reject) with actionable next steps for reviewers. +6. **Interactive Chat**: Reply to any comment with `/Buddy` (e.g., "Why is this wrong? /Buddy") and Review Buddy will explain! --- @@ -68,6 +69,15 @@ I built **Review Buddy** to solve this: - **Quality Score**: `good first review` (90+), `needs work` (<50) - **Security Concerns**: `security` (if Critical/High issues detected) - **Performance Issues**: `performance` (if optimization opportunities found) +- **💡 Best Practices Suggestions**: Identifies code patterns that can be improved: + - Loose equality checks (`==`) → Strict equality (`===`) + - `if (a == undefined)` → `if (!a)` or `if (a === undefined)` + - `var` declarations → `const` or `let` + - Traditional functions → Arrow functions (where appropriate) + - Manual string concatenation → Template literals + - Callback hell → `async/await` or Promises + - For loops → Modern array methods (`map`, `filter`, `reduce`) + - Each suggestion includes before/after code examples with explanations - **🎯 Smart PR Recommendations**: Posts a final recommendation comment with: - **✅ APPROVE**: High quality code (80+), no critical issues - ready to merge - **⚠️ REQUEST CHANGES**: Medium quality (40-79) or some concerns - needs improvements diff --git a/VERSION b/VERSION index bbfcbf1..72abe0e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v4.17 \ No newline at end of file +v5.18 \ No newline at end of file diff --git a/src/index.js b/src/index.js index 276f6ef..cbbb09c 100644 --- a/src/index.js +++ b/src/index.js @@ -163,7 +163,7 @@ async function handlePullRequest(env, adapter, apiKey, model) { // Debug: Log the parsed structure logInfo(`🔍 Parsed Keys: ${Object.keys(analysisResults).join(', ')}`); - logInfo(`🔍 Field Types: review=${typeof analysisResults.review_comment}, perf=${typeof analysisResults.performance_analysis}, sec=${typeof analysisResults.security_analysis}, qual=${typeof analysisResults.quality_analysis}`); + logInfo(`🔍 Field Types: review=${typeof analysisResults.review_comment}, perf=${typeof analysisResults.performance_analysis}, sec=${typeof analysisResults.security_analysis}, qual=${typeof analysisResults.quality_analysis}, best=${typeof analysisResults.best_practices}`); logInfo(`📝 Title Type/Value: ${typeof analysisResults.new_title} = ${analysisResults.new_title === null ? 'null' : analysisResults.new_title === undefined ? 'undefined' : `"${analysisResults.new_title}"`}`); logInfo(`📝 Description Type: ${typeof analysisResults.new_description} = ${analysisResults.new_description === null ? 'null' : analysisResults.new_description === undefined ? 'undefined' : `${String(analysisResults.new_description).substring(0, 100)}...`}`); @@ -172,6 +172,7 @@ async function handlePullRequest(env, adapter, apiKey, model) { performance_analysis, security_analysis, quality_analysis, + best_practices, new_title, new_description, quality_score, @@ -203,6 +204,7 @@ async function handlePullRequest(env, adapter, apiKey, model) { const cleanedPerformance = cleanField(performance_analysis, 'performance_analysis'); const cleanedSecurity = cleanField(security_analysis, 'security_analysis'); const cleanedQuality = cleanField(quality_analysis, 'quality_analysis'); + const cleanedBestPractices = cleanField(best_practices, 'best_practices'); const score = quality_score || 0; const mScore = maintainability_score || 0; @@ -305,8 +307,20 @@ ${footer}`; await postComment(GITHUB_REPOSITORY, prNumber, comment, GITHUB_TOKEN); } - // Step 6: Smart Labels - logInfo("Step 6: Adding smart labels..."); + // Step 6: Best Practices + logInfo("Step 6: Posting best practices suggestions..."); + if (cleanedBestPractices) { + const comment = ` +## 💡 Review Buddy - Best Practices & Alternative Suggestions +> 👥 **Attention:** ${commonMentions} + +${cleanedBestPractices} +${footer}`; + await postComment(GITHUB_REPOSITORY, prNumber, comment, GITHUB_TOKEN); + } + + // Step 7: Smart Labels + logInfo("Step 7: Adding smart labels..."); const finalTitle = (updatePayload.title) || currentTitle; const labelsToAdd = determineLabels(finalTitle, mScore, security_analysis, performance_analysis); @@ -316,8 +330,8 @@ ${footer}`; logInfo("No labels to add."); } - // Step 7: Final Recommendation - logInfo("Step 7: Posting final recommendation..."); + // Step 8: Final Recommendation + logInfo("Step 8: Posting final recommendation..."); const recData = determineRecommendation(mScore, score, cleanedSecurity, cleanedPerformance, tone, language, verdict); let recComment = ` diff --git a/src/prompts/reviewPrompt.js b/src/prompts/reviewPrompt.js index fa60508..a9bf2e5 100644 --- a/src/prompts/reviewPrompt.js +++ b/src/prompts/reviewPrompt.js @@ -70,19 +70,42 @@ Tasks: - Be EXTREMELY detailed (100+ lines) - MUST be a string, NOT an array -5. **PR Metadata**: +5. **Best Practices & Alternative Suggestions** (MUST BE A MARKDOWN STRING): + - Use the EXACT Tone (${tone}) and Language (${lang}) specified above + - Identify code patterns that can be written better using modern best practices + - Examples to look for: + * if (a == undefined) → Suggest: if (!a) or if (a === undefined) + * if (x == null || x == undefined) → Suggest: if (x == null) + * array.length > 0 → Suggest: array.length + * for loops → Suggest: forEach, map, filter, reduce + * var → Suggest: const/let + * function() → Suggest: arrow functions where appropriate + * callback hell → Suggest: async/await or Promises + * repetitive code → Suggest: extract to function/utility + * manual string concatenation → Suggest: template literals + * == → Suggest: === + * object[key] === undefined → Suggest: optional chaining (?.) + - For EACH suggestion provide: + * Current code snippet from the PR + * Better alternative with explanation + * Why it's better (readability, performance, safety) + - Format as markdown with code blocks showing before/after + - If no improvements found, say "Code follows best practices" in the specified tone + - MUST be a string, NOT an array + +6. **PR Metadata**: - Check if current title follows Conventional Commits - If title is GOOD, return null for new_title - ONLY suggest new_title if it's vague or violates conventions - Generate comprehensive PR description (Markdown) with Summary, Changes, Verification - If needsDesc is "true", provide new_description. If "false", return null -6. **Overall Benchmark Score (0-100)**: +7. **Overall Benchmark Score (0-100)**: - Calculate comprehensive maintainability score - Weigh: Code Quality (30%), Security (25%), Performance (25%), Maintainability (20%) - Scoring: 90-100 Excellent, 70-89 Good, 50-69 Needs Improvement, 0-49 Poor -7. **Verdict**: +8. **Verdict**: - Consider PERSPECTIVE and PURPOSE of changes - Evaluate ACTUAL impact and risk - Verdict: "APPROVE", "REQUEST_CHANGES", or "REJECT" @@ -99,6 +122,7 @@ Output JSON with this EXACT structure: "performance_analysis": "", "security_analysis": "", "quality_analysis": "", + "best_practices": "", "new_title": "", "new_description": "", "quality_score": ,