This is an automated email from the ASF dual-hosted git repository.

rawkintrevo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/mahout.git


The following commit(s) were added to refs/heads/main by this push:
     new ac5c51347 MAHOUT-506: Add gofannon PR Review (#514)
ac5c51347 is described below

commit ac5c5134729be9aa27640585db800a73eb08cd54
Author: Trevor Grant <[email protected]>
AuthorDate: Tue Mar 11 21:15:11 2025 -0500

    MAHOUT-506: Add gofannon PR Review (#514)
    
    * Add gofannon PR Review
    
    * Added ASF License Headers
---
 .github/scripts/checks/__init__.py       |  16 +++++
 .github/scripts/checks/general_review.py | 119 +++++++++++++++++++++++++++++++
 .github/scripts/review_pr.py             |  46 ++++++++++++
 .github/workflows/pr_review.yml          |  47 ++++++++++++
 4 files changed, 228 insertions(+)

diff --git a/.github/scripts/checks/__init__.py 
b/.github/scripts/checks/__init__.py
new file mode 100644
index 000000000..cce3acad3
--- /dev/null
+++ b/.github/scripts/checks/__init__.py
@@ -0,0 +1,16 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
diff --git a/.github/scripts/checks/general_review.py 
b/.github/scripts/checks/general_review.py
new file mode 100644
index 000000000..9215e5a1f
--- /dev/null
+++ b/.github/scripts/checks/general_review.py
@@ -0,0 +1,119 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import ast
+from github import Github
+
+class GeneralReviewCheck:
+    def __init__(self, client, model_name):
+        self.client = client
+        self.model_name = model_name
+
+    def process_pr_file(self, file, repo, pr):
+        comments = []
+        analyzed = False
+
+        if file.filename.endswith('.py'):
+            analyzed = True
+            content = repo.get_contents(file.filename, 
ref=pr.head.sha).decoded_content.decode()
+
+            # Basic code analysis
+            try:
+                tree = ast.parse(content)
+                analysis = self.analyze_code_structure(tree)
+                if analysis:
+                    comments.append({
+                        "path": file.filename,
+                        "body": analysis,
+                        "line": 1
+                    })
+            except SyntaxError as e:
+                comments.append({
+                    "path": file.filename,
+                    "body": f"⚠️ Syntax error found:\n{e}",
+                    "line": 1
+                })
+
+        return comments, analyzed
+
+    def analyze_code_structure(self, tree):
+        analysis = []
+
+        # Check for large classes
+        for node in ast.walk(tree):
+            if isinstance(node, ast.ClassDef):
+                methods = [n for n in node.body if isinstance(n, 
ast.FunctionDef)]
+                if len(methods) > 10:
+                    analysis.append(f"- Class '{node.name}' has {len(methods)} 
methods. Consider splitting into smaller classes.")
+
+                    # Check for long functions
+        for node in ast.walk(tree):
+            if isinstance(node, ast.FunctionDef):
+                lines = node.end_lineno - node.lineno if node.end_lineno else 0
+                if lines > 50:
+                    analysis.append(f"- Function '{node.name}' is {lines} 
lines long. Consider breaking it into smaller functions.")
+
+                    # Check for TODO comments
+        for node in ast.walk(tree):
+            if isinstance(node, ast.Expr) and isinstance(node.value, 
ast.Constant):
+                if isinstance(node.value.value, str) and 'TODO' in 
node.value.value.upper():
+                    analysis.append(f"- TODO comment found: 
{node.value.value}")
+
+        if analysis:
+            return "🔍 Code structure analysis:\n" + "\n".join(analysis)
+        return None
+
+    def generate_general_impression(self, pr):
+        prompt = f"""Provide a general impression of this pull request. 
Consider:  
+- Overall code quality  
+- Code organization  
+- Documentation  
+- Potential improvements  
+- Areas that need special attention  
+  
+Pull Request Details:  
+Title: {pr.title}  
+Description: {pr.body}  
+Files Changed: {pr.changed_files}  
+Additions: {pr.additions}  
+Deletions: {pr.deletions}  
+  
+Provide your analysis in markdown format with these sections:  
+1. Overall Impression  
+2. Strengths  
+3. Areas for Improvement  
+4. Special Attention Needed"""
+
+        response = self.client.chat.completions.create(
+            model=self.model_name,
+            messages=[{
+                "role": "system",
+                "content": "You are an experienced code reviewer. Provide a 
high-level analysis of pull requests."
+            }, {
+                "role": "user",
+                "content": prompt
+            }]
+        )
+
+        return response.choices[0].message.content
+
+    def process_pr(self, pr):
+        general_analysis = self.generate_general_impression(pr)
+        return [{
+            "path": "GENERAL",
+            "body": general_analysis,
+            "line": 0
+        }], True
diff --git a/.github/scripts/review_pr.py b/.github/scripts/review_pr.py
new file mode 100644
index 000000000..5b283433b
--- /dev/null
+++ b/.github/scripts/review_pr.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import os
+import sys
+from github import Github
+from gofannon.github.pr_review_tool import PRReviewTool
+
+def check_env_vars():
+    required_vars = [
+        'GITHUB_TOKEN', 'OPENAI_API_KEY', 'OPENAI_BASE_URL', 
'OPENAI_MODEL_NAME', 'PR_NUMBER', 'REPO_NAME'
+    ]
+    for var in required_vars:
+        if not os.environ.get(var):
+            sys.exit(f"Error: Required environment variable '{var}' is 
missing.")
+
+check_env_vars()
+
+def main():
+    pr_number = int(os.environ['PR_NUMBER'])
+    repo_name = os.environ['REPO_NAME']
+    pr_review_tool = PRReviewTool()
+    review_summary = pr_review_tool.fn(pr_number=pr_number, 
repo_name=repo_name)
+
+    # Post the review comment to the pull request using PyGithub.
+    g = Github(os.environ['GITHUB_TOKEN'])
+    repo = g.get_repo(repo_name)
+    pr = repo.get_pull(pr_number)
+    pr.create_issue_comment(review_summary)
+
+if __name__ == "__main__":
+    main()
diff --git a/.github/workflows/pr_review.yml b/.github/workflows/pr_review.yml
new file mode 100644
index 000000000..fafc1f446
--- /dev/null
+++ b/.github/workflows/pr_review.yml
@@ -0,0 +1,47 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+name: PR Tool Review
+on:
+  pull_request_target:
+    types: [labeled]
+
+jobs:
+  review:
+    if: github.event.label.name == 'run-tests'
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out base repository
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: '3.10'
+      - name: Install Gofannon
+        run: |
+          pip install gofannon
+      - name: Run PR Review Tool
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
+          OPENAI_BASE_URL: "https://api.deepinfra.com/v1/openai";
+          OPENAI_MODEL_NAME: "meta-llama/Llama-3.3-70B-Instruct-Turbo"
+          PR_NUMBER: ${{ github.event.pull_request.number }}
+          REPO_NAME: ${{ github.repository }}
+        run: |
+          poetry run python .github/scripts/review_pr.py

Reply via email to