Skip to content

Utilize Groq to comment MR suggestions - #1

Merged
banstack merged 2 commits into
mainfrom
test-change
Jun 6, 2025
Merged

Utilize Groq to comment MR suggestions#1
banstack merged 2 commits into
mainfrom
test-change

Conversation

@banstack

@banstackbanstack commented Jun 6, 2025

Copy link
Copy Markdown
Owner

Description

This contains the initial changes for implementing code review bot using GitHub actions and Groq API.

  • Here we make an API request to Groq API using llama-4-scout as our LLM of choice
  • We make a request to GitHub API for diff information

@banstack
banstackforce-pushed the test-change branch 2 times, most recently from 178fd58 to 3f3e415CompareJune 6, 2025 04:48
@github-actions

Copy link
Copy Markdown

Code Review

The provided code diff appears to be implementing a code review bot using GitHub Actions and the Groq API. Here are some improvements:

Security and Best Practices

  • In .github/workflows/code-review.yml, consider pinning the actions/checkout version to a specific commit hash for better security.
  • In reviewbot/main.py, avoid hardcoding API keys and secrets. Instead, use environment variables or a secrets manager.
  • In reviewbot/utils.py, handle exceptions more robustly. For example, what if the GITHUB_EVENT_PATH environment variable is set but the file is not a valid JSON?

Code Quality and Readability

  • In reviewbot/main.py, consider adding type hints for function parameters and return types.
  • In reviewbot/utils.py, use more descriptive variable names. For example, repo could be github_repository.
  • In reviewbot/utils.py, consider adding docstrings to explain the purpose of each function.

Functionality

  • In reviewbot/main.py, what if the Groq API returns an error? Consider adding error handling.
  • In reviewbot/utils.py, what if the GitHub API returns an error? Consider adding error handling.
  • In reviewbot/utils.py, the get_diff function assumes that the GitHub API returns a paginated response. Consider adding a check for this.

Performance

  • In reviewbot/utils.py, the get_diff function makes multiple API calls to fetch the diff. Consider batching these requests or using a more efficient approach.

Code Suggestions

  • Consider adding a timeout parameter to the requests.post call in reviewbot/main.py to avoid hanging indefinitely.
  • In reviewbot/utils.py, use a more efficient way to check if a file has a patch. For example, use if f.get("patch", "").strip():

Updated Code

Here is an updated version of the code incorporating some of these suggestions:

.github/workflows/code-review.yml:

jobs:
review:
runs-on: ubuntu-latestpermissions:
contents: readpull-requests: writesteps:
- name: Checkout codeuses: actions/checkout@v4@1234567890abcdef
- name: Install dependenciesrun: | pip install -r requirements.txt - name: Run LLM code reviewenv:
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}PYTHONPATH: ${{ github.workspace }}GITHUB_REPOSITORY: ${{ github.repository }}GITHUB_REF: ${{ github.ref }}run: | python3 -m reviewbot.main

reviewbot/main.py:

importosimportrequestsfromreviewbot.utilsimportget_diff, post_pr_comment, get_pr_numberdefreview_with_groq(diff: str) ->str:
api_key=os.environ.get("GROQ_API_KEY")
headers= {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
payload= {
"model": "meta-llama/llama-4-scout-17b-16e-instruct",
"messages": [
{"role": "system", "content": "You are a senior software engineer doing code reviews."},
{"role": "user", "content": f"Please review this code diff, list improvements in bullet points:\n\n{diff}"}
],
"temperature": 0.3,
}
try:
response=requests.post("https://api.groq.com/openai/v1/chat/completions", headers=headers, json=payload, timeout=30)
response.raise_for_status()
returnresponse.json()["choices"][0]["message"]["content"]
exceptrequests.RequestExceptionase:
print(f"Error: {e}")
return""defmain():
diff=get_diff()
review=review_with_groq(diff)
post_pr_comment(review)
if__name__=="__main__":
main()

reviewbot/utils.py:

importosimportrequestsimportjsondefget_pr_number() ->int:
event_path=os.getenv("GITHUB_EVENT_PATH")
ifnotevent_path:
raiseException("GITHUB_EVENT_PATH not set")
withopen(event_path, 'r') asf:
event=json.load(f)
returnevent["pull_request"]["number"]
defget_diff() ->str:
github_repository=os.environ.get("GITHUB_REPOSITORY")
pr_number=get_pr_number()
token=os.environ.get("GITHUB_TOKEN")
ifnottoken:
raiseException("Missing GITHUB_TOKEN environment variable.")
headers= {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
}
url=f"https://api.github.com/repos/{github_repository}/pulls/{pr_number}/files"diffs= []
page=1whileTrue:
response=requests.get(url, headers=headers, params={"page": page, "per_page": 100})
response.raise_for_status()
files=response.json()
ifnotfiles:
breakforfinfiles:
patch=f.get("patch", "").strip()
ifpatch:
diffs.append(f"File: {f['filename']}\n{patch}")
page+=1return"\n\n".join(diffs)
defpost_pr_comment(body: str):
github_repository=os.getenv("GITHUB_REPOSITORY")
token=os.getenv("GITHUB_TOKEN")
pr_number=get_pr_number()
url=f"https://api.github.com/repos/{github_repository}/issues/{pr_number}/comments"headers= {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github+json"
}
payload= {
"body": body
}
try:
response=requests.post(url, headers=headers, json=payload, timeout=30)
response.raise_for_status()
exceptrequests.RequestExceptionase:
print(f"Error: {e}")

@github-actions

Copy link
Copy Markdown

Here are the improvements in bullet points:

Code Quality and Best Practices

  • In .github/workflows/code-review.yml, consider adding a timeout to the job to prevent it from running indefinitely.
  • In reviewbot/main.py, the review_with_groq function does not handle exceptions well. Consider adding try-except blocks to handle potential errors.
  • In reviewbot/utils.py, the get_diff function does not handle pagination correctly. Although the code attempts to paginate, it does not account for the possibility of multiple pages of results. Consider using a more robust pagination approach.
  • In reviewbot/utils.py, the post_pr_comment function does not validate the body parameter. Consider adding a check to ensure that the comment body is not empty.

Security

  • In .github/workflows/code-review.yml, the GROQ_API_KEY and GITHUB_TOKEN are stored as secrets. However, it's still important to ensure that these secrets are not leaked in the workflow logs. Consider adding a step to mask these secrets.
  • In reviewbot/main.py, the api_key is retrieved from an environment variable. Consider using a more secure approach, such as using a secrets manager.

Performance

  • In reviewbot/utils.py, the get_diff function makes multiple API calls to retrieve the diff. Consider batching these calls or using a more efficient approach to retrieve the diff.

Readability and Maintainability

  • In reviewbot/main.py, the review_with_groq function has a magic string for the API endpoint. Consider defining a constant for this endpoint.
  • In reviewbot/utils.py, the get_diff function has a magic string for the GitHub API endpoint. Consider defining a constant for this endpoint.
  • In reviewbot/utils.py, the post_pr_comment function has a magic string for the GitHub API endpoint. Consider defining a constant for this endpoint.

Testing

  • There are no tests for the reviewbot code. Consider adding unit tests and integration tests to ensure that the code works correctly.

Code Style

  • In reviewbot/main.py, the code uses inconsistent indentation. Consider using a consistent number of spaces for indentation.
  • In reviewbot/utils.py, the code uses inconsistent naming conventions. Consider using a consistent naming convention throughout the codebase.

Here is an updated version of the code incorporating some of these suggestions:

.github/workflows/code-review.yml

name: Code Reviewon:
pull_request:
types: [opened, synchronize]jobs:
review:
runs-on: ubuntu-latestpermissions:
contents: readpull-requests: writesteps:
- name: Checkout codeuses: actions/checkout@v3
- name: Set up Pythonuses: actions/setup-python@v2with:
python-version: '3.9'
- name: Install dependenciesrun: | pip install -r requirements.txt - name: Run LLM code reviewenv:
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}PYTHONPATH: ${{ github.workspace }}GITHUB_REPOSITORY: ${{ github.repository }}GITHUB_REF: ${{ github.ref }}run: | python3 -m reviewbot.main

reviewbot/main.py

importosimportrequestsfromreviewbot.utilsimportget_diff, post_pr_comment, get_pr_numberGROQ_API_ENDPOINT="https://api.groq.com/openai/v1/chat/completions"defreview_with_groq(diff):
try:
api_key=os.environ.get("GROQ_API_KEY")
headers= {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
payload= {
"model": "meta-llama/llama-4-scout-17b-16e-instruct",
"messages": [
{"role": "system", "content": "You are a senior software engineer doing code reviews."},
{"role": "user", "content": f"Please review this code diff, list improvements in bullet points:\n\n{diff}"}
],
"temperature": 0.3,
}
response=requests.post(GROQ_API_ENDPOINT, headers=headers, json=payload)
response.raise_for_status()
returnresponse.json()["choices"][0]["message"]["content"]
exceptrequests.exceptions.RequestExceptionase:
print(f"Error: {e}")
return""defmain():
diff=get_diff()
review=review_with_groq(diff)
post_pr_comment(review)
if__name__=="__main__":
main()

reviewbot/utils.py

importosimportrequestsimportjsonGITHUB_API_ENDPOINT="https://api.github.com"defget_pr_number():
event_path=os.getenv("GITHUB_EVENT_PATH")
ifnotevent_path:
raiseException("GITHUB_EVENT_PATH not set")
withopen(event_path, 'r') asf:
event=json.load(f)
returnevent["pull_request"]["number"]
defget_diff():
repo=os.environ.get("GITHUB_REPOSITORY") pr_number=get_pr_number()
token=os.environ.get("GITHUB_TOKEN")
ifnottoken:
raiseException("Missing GITHUB_TOKEN environment variable.")
headers= {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3+json",
}
url=f"{GITHUB_API_ENDPOINT}/repos/{repo}/pulls/{pr_number}/files"diffs= []
page=1whileTrue:
response=requests.get(url, headers=headers, params={"page": page, "per_page": 100})
response.raise_for_status()
files=response.json()
ifnotfiles:
breakforfinfiles:
patch=f.get("patch")
ifpatch:
diffs.append(f"File: {f['filename']}\n{patch}")
page+=1return"\n\n".join(diffs)
defpost_pr_comment(body: str):
repo=os.getenv("GITHUB_REPOSITORY")
token=os.getenv("GITHUB_TOKEN")
pr_number=get_pr_number()
url=f"{GITHUB_API_ENDPOINT}/repos/{repo}/issues/{pr_number}/comments"headers= {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github+json"
}
payload= {
"body": body
}
response=requests.post(url, headers=headers, json=payload)
print("GitHub API response:", response.status_code, response.text)
response.raise_for_status()

@github-actions

Copy link
Copy Markdown

Code Review

The provided code diff appears to be implementing a code review bot using GitHub Actions and the Groq API. Here are some improvements:

Security and Best Practices

  • In .github/workflows/code-review.yml, consider pinning the actions/checkout version to a specific commit hash for better security.
  • In reviewbot/main.py, avoid hardcoding sensitive information like API keys. Instead, use environment variables or a secrets manager.
  • In reviewbot/utils.py, handle exceptions more robustly. For example, what if the GITHUB_EVENT_PATH environment variable is set but the file is not found?

Code Quality and Readability

  • In reviewbot/main.py, consider adding type hints for function parameters and return types.
  • In reviewbot/utils.py, use more descriptive variable names, such as github_token instead of token.
  • In reviewbot/utils.py, consider adding docstrings to functions to explain their purpose and behavior.

Functionality

  • In reviewbot/main.py, what if the Groq API returns an error or an empty response? Consider adding error handling and logging.
  • In reviewbot/utils.py, what if the GitHub API returns an error or an empty response? Consider adding error handling and logging.
  • In reviewbot/utils.py, the get_diff function assumes that the GitHub API returns a paginated response. Consider adding a check for this and handling pagination more robustly.

Performance

  • In reviewbot/utils.py, the get_diff function makes multiple API calls to fetch the diff. Consider batching these requests or using a more efficient approach.

Code Suggestions

Here are some specific code suggestions:

  • In .github/workflows/code-review.yml, add a permissions block to restrict the workflow's permissions:
permissions:
contents: readpull-requests: write
  • In reviewbot/main.py, use a more descriptive variable name for the Groq API response:
groq_response=response.json()
review=groq_response["choices"][0]["message"]["content"]
  • In reviewbot/utils.py, use a more descriptive variable name for the GitHub API response:
github_response=response.json()
  • In reviewbot/utils.py, consider adding a try-except block to handle exceptions:
try:
# API callexceptrequests.RequestExceptionase:
print(f"Error: {e}")

Updated Code

Here is an updated version of the code incorporating some of these suggestions:

.github/workflows/code-review.yml:

name: Code Reviewon:
pull_request:
types: [opened, synchronize]jobs:
review:
runs-on: ubuntu-latestpermissions:
contents: readpull-requests: writesteps:
- name: Checkout codeuses: actions/checkout@v3
- name: Install dependenciesrun: | pip install -r requirements.txt - name: Run LLM code reviewenv:
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}PYTHONPATH: ${{ github.workspace }}GITHUB_REPOSITORY: ${{ github.repository }}GITHUB_REF: ${{ github.ref }}run: | python3 -m reviewbot.main

reviewbot/main.py:

importosimportrequestsfromreviewbot.utilsimportget_diff, post_pr_comment, get_pr_numberdefreview_with_groq(diff: str) ->str:
api_key=os.environ.get("GROQ_API_KEY")
headers= {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
payload= {
"model": "meta-llama/llama-4-scout-17b-16e-instruct",
"messages": [
{"role": "system", "content": "You are a senior software engineer doing code reviews."},
{"role": "user", "content": f"Please review this code diff, list improvements in bullet points:\n\n{diff}"}
],
"temperature": 0.3,
}
try:
response=requests.post("https://api.groq.com/openai/v1/chat/completions", headers=headers, json=payload)
response.raise_for_status()
groq_response=response.json()
review=groq_response["choices"][0]["message"]["content"]
returnreviewexceptrequests.RequestExceptionase:
print(f"Error: {e}")
return""defmain():
diff=get_diff()
review=review_with_groq(diff)
post_pr_comment(review)
if__name__=="__main__":
main()

reviewbot/utils.py:

importosimportrequestsimportjsondefget_pr_number() ->int:
event_path=os.getenv("GITHUB_EVENT_PATH")
ifnotevent_path:
raiseException("GITHUB_EVENT_PATH not set")
withopen(event_path, 'r') asf:
event=json.load(f)
returnevent["pull_request"]["number"]
defget_diff() ->str:
repo=os.environ.get("GITHUB_REPOSITORY") pr_number=get_pr_number()
github_token=os.environ.get("GITHUB_TOKEN")
ifnotgithub_token:
raiseException("Missing GITHUB_TOKEN environment variable.")
headers= {
"Authorization": f"Bearer {github_token}",
"Accept": "application/vnd.github.v3+json",
}
url=f"https://api.github.com/repos/{repo}/pulls/{pr_number}/files"diffs= []
page=1whileTrue:
try:
response=requests.get(url, headers=headers, params={"page": page, "per_page": 100})
response.raise_for_status()
files=response.json()
ifnotfiles:
breakforfinfiles:
patch=f.get("patch")
ifpatch:
diffs.append(f"File: {f['filename']}\n{patch}")
page+=1exceptrequests.RequestExceptionase:
print(f"Error: {e}")
breakreturn"\n\n".join(diffs)
defpost_pr_comment(body: str):
repo=os.getenv("GITHUB_REPOSITORY")
github_token=os.getenv("GITHUB_TOKEN")
pr_number=get_pr_number()
url=f"https://api.github.com/repos/{repo}/issues/{pr_number}/comments"headers= {
"Authorization": f"Bearer {github_token}",
"Accept": "application/vnd.github+json"
}
payload= {
"body": body
}
try:
response=requests.post(url, headers=headers, json=payload)
response.raise_for_status()
exceptrequests.RequestExceptionase:
print(f"Error: {e}")

@banstackbanstack changed the title Add twosum example to hello.pyUtilize Groq to comment MR suggestionsJun 6, 2025
@banstack
banstack merged commit 67394ff into mainJun 6, 2025
banstack added a commit that referenced this pull request Jun 8, 2025
* Add two-sum example
* Allow GH action to post review as comment
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@banstack