From dac8b50002cbd5066755b63d5afb7c74a9b09a21 Mon Sep 17 00:00:00 2001 From: Bryan Montalvan Date: Fri, 6 Jun 2025 00:30:33 -0400 Subject: [PATCH 1/4] Initial commit --- .github/workflows/code-review.yml | 25 +++++++++++++++++++++++++ README.md | 1 + reviewbot/main.py | 29 +++++++++++++++++++++++++++++ reviewbot/utils.py | 10 ++++++++++ test_module/hello.py | 6 ++++++ 5 files changed, 71 insertions(+) create mode 100644 .github/workflows/code-review.yml create mode 100644 README.md create mode 100644 reviewbot/main.py create mode 100644 reviewbot/utils.py create mode 100644 test_module/hello.py diff --git a/.github/workflows/code-review.yml b/.github/workflows/code-review.yml new file mode 100644 index 0000000..8e6b610 --- /dev/null +++ b/.github/workflows/code-review.yml @@ -0,0 +1,25 @@ +name: LLM Code Review + +on: + pull_request: + types: [opened, synchronize] + +jobs: + review: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install dependencies + run: | + pip install -r requirements.txt + + - name: Run code review + run: | + python reviewbot/main.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..830f5a5 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# LLM Code Review Bot \ No newline at end of file diff --git a/reviewbot/main.py b/reviewbot/main.py new file mode 100644 index 0000000..83c0f30 --- /dev/null +++ b/reviewbot/main.py @@ -0,0 +1,29 @@ +import os +import requests +from reviewbot.utils import get_diff + +def review_with_groq(diff): + api_key = os.environ.get("GROQ_API_KEY") + headers = { + "Authorization": f"Bearer {api_key}", + "Content-Type": "application/json", + } + payload = { + "model": "mixtral-8x7b-32768", + "messages": [ + {"role": "system", "content": "You are a senior software engineer doing code reviews."}, + {"role": "user", "content": f"Please review this code diff:\n\n{diff}"} + ], + "temperature": 0.3, + } + + response = requests.post("https://api.groq.com/openai/v1/chat/completions", headers=headers, json=payload) + return response.json()["choices"][0]["message"]["content"] + +def main(): + diff = get_diff() + review = review_with_groq(diff) + print("::notice file=test_module/hello.py,line=1::" + review.replace("\n", " ")) + +if __name__ == "__main__": + main() diff --git a/reviewbot/utils.py b/reviewbot/utils.py new file mode 100644 index 0000000..dcb02fb --- /dev/null +++ b/reviewbot/utils.py @@ -0,0 +1,10 @@ +# reviewbot/utils.py + +def get_diff(): + # In real setup, parse `git diff` or PR files + return "def hello(name):\n print('Hello ' + name)" + +def fake_llm_review(diff): + if "print" in diff: + return "Consider using logging instead of print for better production code quality." + return "No issues found." diff --git a/test_module/hello.py b/test_module/hello.py new file mode 100644 index 0000000..230ef63 --- /dev/null +++ b/test_module/hello.py @@ -0,0 +1,6 @@ +# test_module/hello.py + +def hello(name): + print("Hello " + name) + +hello("World") From 4e0bc872322aba9b1f0a4bcf4687fbc6263041d9 Mon Sep 17 00:00:00 2001 From: Bryan Montalvan Date: Fri, 6 Jun 2025 00:40:47 -0400 Subject: [PATCH 2/4] Added requirements.txt for Groq review script --- requirements.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..112eec9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,12 @@ +certifi==2025.4.26 +cffi==1.16.0 +charset-normalizer==3.4.2 +cryptography==41.0.5 +greenlet==1.1.2 +idna==3.10 +msgpack==1.0.2 +pycparser==2.21 +pycryptodome==3.19.0 +pynvim==0.4.3 +requests==2.32.3 +urllib3==2.4.0 From 67394ff4b03c63aa0b6123d7c19165376f10102f Mon Sep 17 00:00:00 2001 From: Bryan Date: Fri, 6 Jun 2025 01:19:37 -0400 Subject: [PATCH 3/4] Utilize Groq to comment MR suggestions (#1) * Add two-sum example * Allow GH action to post review as comment --- .github/workflows/code-review.yml | 15 ++++- reviewbot/__pycache__/main.cpython-310.pyc | Bin 0 -> 1266 bytes reviewbot/__pycache__/utils.cpython-310.pyc | Bin 0 -> 1039 bytes reviewbot/main.py | 11 ++-- reviewbot/utils.py | 68 ++++++++++++++++++-- test_module/hello.py | 10 +-- 6 files changed, 86 insertions(+), 18 deletions(-) create mode 100644 reviewbot/__pycache__/main.cpython-310.pyc create mode 100644 reviewbot/__pycache__/utils.cpython-310.pyc diff --git a/.github/workflows/code-review.yml b/.github/workflows/code-review.yml index 8e6b610..576479e 100644 --- a/.github/workflows/code-review.yml +++ b/.github/workflows/code-review.yml @@ -7,6 +7,11 @@ on: jobs: review: runs-on: ubuntu-latest + + permissions: + contents: read + pull-requests: write + steps: - name: Checkout code uses: actions/checkout@v3 @@ -20,6 +25,12 @@ jobs: run: | pip install -r requirements.txt - - name: Run code review + - name: Run LLM code review + env: + GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PYTHONPATH: ${{ github.workspace }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_REF: ${{ github.ref }} run: | - python reviewbot/main.py + python3 -m reviewbot.main diff --git a/reviewbot/__pycache__/main.cpython-310.pyc b/reviewbot/__pycache__/main.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e9b088cecc1d54614cd267904f77773cab37f6c1 GIT binary patch literal 1266 zcmYjQQE%He5GEkoLkk$|wk8|8VL;Zk+e7stFyh%(B8e(V zC$nMiC41d3SOz4I`#pQp>z?)(GN9YhYKsuKBY8*izWaD52ZJ8L@vqsRed7}Hx82+v z3^!k*=zUaz2wIS&ooPaG&k9yLi9?BSg!?N=T+tC-oIB7J-U(Cpp>s~qOJ8gx^#8$k z$YDque+niQ`DBt&YkD&}I9oYD(Z8TF#~0!D+85@eq7YB3`;OPDhgimc%!3FBb~{)iS`~HMSBk+$}4TuJTpyKFSLPj z`S7Kj2N*8kfrcuVD$sIb&a4HhX!7`p1Q|oaY z^Ew|*m3%eIWEsmEDxSxudvP}7CPq_TfaOPrtnp^R1t{IPmaOIObAA>)#hZv)*LVcR ziI>e}o`F`jA{y^aXoYo2!d}CqZakdIAg8MQh^Kd{Ia)5`4df_9sz8^jsgr zKOv7gK2i%_mB=kGPI(o71^UFu8h^EnY|yCvi0DX~xLw*+$@6MdFPdR%O3!jLOD%V{ z-t~v5`qXEPc3-oO&u&rnnz`NU;nvXc*#}hZ;(-k1-LS1`@ork>BU~7APS(WG6*DCS z8``_3LFg(QZ-YV&aMgGU>VjtwGPQ&Iq}!&oA*xlk?J?J;ZIja$YnS>Ib9vu-{4}+` zGz~qqg$C6}mF&DDY&17{p>KqJd#mClr0I=7_HWcCn*Ujw#^<(zw6*)hrTAOanXJYLHN7%{A`VCg>r3_8V2h+pC6 z+9oT!3|O$jEWC{xY>~QUvA%6W7X5;M##b3JWDraA2jFjcKT9lmfnE{TX6Z}P1Z=~i z7l>_I4A^-UHQ@v`5!-6wHZsvEv7rrY%xL^mKP{ zwEyJr`0>f%(f4`!#`X1UoL&42viSU4p|vO{-G{bxse_sLPWtY<^6 zy1bkVCCeEvO?OU}pu>Xee!h8C^5pQF{e#7aZ;D;^UVHyHwZCZXa;l*4;x4VKLX4;p zvdrcs>raH4*2Dh%M}(;+0w4nHp2+`&mXSah)`hvur&= zwrFKlT@*T7#MxK?*$WI`{N#cGLd~$E6P_m(R|9W>r#0o2aiv{cQAKCkMHMxpsl#b6 zbwp~{x;g_FOt^882G+*4_kZ+cfV)c+KdZSm+TBo8Xg(NAHPD8dTD#DX;$j$;mkf4N zl)a5S^i=b9r3RO$>>?wd^HQ~eqYG+P?6tkU?WPC^Qx!^zS45fji@}{?HBMRNG&Rqh- z4SZL)e@K4 Date: Fri, 6 Jun 2025 01:20:39 -0400 Subject: [PATCH 4/4] Slow twosum solution --- .github/mode-context.json | 18 ++++++++++++++++++ reviewbot/main.py | 4 +++- reviewbot/utils.py | 2 +- test_module/hello.py | 11 ++++++++--- 4 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 .github/mode-context.json diff --git a/.github/mode-context.json b/.github/mode-context.json new file mode 100644 index 0000000..3d0ee49 --- /dev/null +++ b/.github/mode-context.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://raw.githubusercontent.com/github/context-server/main/schema.json", + "name": "LLM Code Review Bot", + "description": "A bot that uses LLMs to review pull request code diffs and post comments.", + "app": { + "name": "llm-code-review-bot", + "version": "0.1.0" + }, + "config": { + "entrypoint": "reviewbot.main:main", + "runtime": { + "language": "python" + } + }, + "capabilities": { + "pullRequestReview": true + } +} diff --git a/reviewbot/main.py b/reviewbot/main.py index 0b5c570..29ecb8d 100644 --- a/reviewbot/main.py +++ b/reviewbot/main.py @@ -2,6 +2,8 @@ import requests from reviewbot.utils import get_diff, post_pr_comment, get_pr_number +llm_prompt = "Please reviiew thsi code diff, list improvements and potential optimizations in bullet points"; + def review_with_groq(diff): api_key = os.environ.get("GROQ_API_KEY") headers = { @@ -12,7 +14,7 @@ def review_with_groq(diff): "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}"} + {"role": "user", "content": f"{llm_prompt} given the following diff{diff}"} ], "temperature": 0.3, } diff --git a/reviewbot/utils.py b/reviewbot/utils.py index 9049894..3d7249c 100644 --- a/reviewbot/utils.py +++ b/reviewbot/utils.py @@ -13,7 +13,7 @@ def get_pr_number(): return event["pull_request"]["number"] def get_diff(): - repo = os.environ.get("GITHUB_REPOSITORY") # e.g. "owner/repo" + repo = os.environ.get("GITHUB_REPOSITORY") pr_number = get_pr_number() token = os.environ.get("GITHUB_TOKEN") diff --git a/test_module/hello.py b/test_module/hello.py index eb53221..326fe9f 100644 --- a/test_module/hello.py +++ b/test_module/hello.py @@ -1,6 +1,11 @@ # Hello.py: A sample python script used for testing reviews -def helloWorld(): - print("Hello World") +def twoSum(array, targetSum): + for i in range(0, len(array)): + for j in range(i+1, len(array)): + if array[i] + array[j] == targetSum: + return ([array[i], array[j]]) + return [] -helloWorld() +twoSum([2,7,11,15], 9) +