From 4d640128eb7c822c31be7ed307741dc2fa22a20d Mon Sep 17 00:00:00 2001 From: jeetsondbritto <168982992+jeetsondbritto@users.noreply.github.com> Date: Sat, 31 Jan 2026 15:41:45 -0500 Subject: [PATCH 1/7] Add multiply function, tests, and CI workflow --- .github/workflows/ci.yml | 26 ++++++++++++++++++++++++++ app.py | 3 +++ tests/test_app.py | 5 ++++- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..d0863fdd --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Run tests + run: pytest -v diff --git a/app.py b/app.py index 8f2f7ae1..e3eed4a7 100644 --- a/app.py +++ b/app.py @@ -5,6 +5,9 @@ def add(a: int, b: int) -> int: """Add two numbers together.""" return a + b +def multiply(a: int, b: int) -> int: + """Multiply two numbers together.""" + return a * b def is_even(n: int) -> bool: """Check if a number is even.""" diff --git a/tests/test_app.py b/tests/test_app.py index 79c3e093..6d1aa92b 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,6 +1,6 @@ """Tests for app.py - you'll add more!""" -from app import add, is_even, reverse_string +from app import add, is_even, reverse_string, multiply class TestMath: @@ -8,6 +8,9 @@ class TestMath: def test_add_positive(self): assert add(2, 3) == 5 + + def test_multiply(self): + assert multiply(9, 9) == 81 def test_add_negative(self): assert add(-1, -1) == -2 From 3a9b3b8c641a29c059ff73ff3b9bb6ecbfcfa562 Mon Sep 17 00:00:00 2001 From: jeetsondbritto <168982992+jeetsondbritto@users.noreply.github.com> Date: Sat, 31 Jan 2026 15:47:04 -0500 Subject: [PATCH 2/7] Break a test --- tests/test_app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_app.py b/tests/test_app.py index 6d1aa92b..bcf55228 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -10,7 +10,8 @@ def test_add_positive(self): assert add(2, 3) == 5 def test_multiply(self): - assert multiply(9, 9) == 81 + assert multiply(9, 9) == 18 + def test_add_negative(self): assert add(-1, -1) == -2 From 0907482c6e68951565b1e0260a527162e2900510 Mon Sep 17 00:00:00 2001 From: jeetsondbritto <168982992+jeetsondbritto@users.noreply.github.com> Date: Sat, 31 Jan 2026 15:50:36 -0500 Subject: [PATCH 3/7] Fix the test --- tests/test_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_app.py b/tests/test_app.py index bcf55228..96c6f8e3 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -10,7 +10,7 @@ def test_add_positive(self): assert add(2, 3) == 5 def test_multiply(self): - assert multiply(9, 9) == 18 + assert multiply(9, 9) == 81 def test_add_negative(self): From 4b8e58baccfc76cbc01bd27a8ca58d49d3e79185 Mon Sep 17 00:00:00 2001 From: jeetsondbritto <168982992+jeetsondbritto@users.noreply.github.com> Date: Sat, 31 Jan 2026 21:57:07 -0500 Subject: [PATCH 4/7] Re-Run the test for divide --- app.py | 4 ++++ tests/test_app.py | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app.py b/app.py index e3eed4a7..ec526ea5 100644 --- a/app.py +++ b/app.py @@ -9,6 +9,10 @@ def multiply(a: int, b: int) -> int: """Multiply two numbers together.""" return a * b +def divide(a: int, b: int) -> int: + """Divide two numbers together.""" + return a / b + def is_even(n: int) -> bool: """Check if a number is even.""" return n % 2 == 0 diff --git a/tests/test_app.py b/tests/test_app.py index 96c6f8e3..c9a0b0ec 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,6 +1,6 @@ """Tests for app.py - you'll add more!""" -from app import add, is_even, reverse_string, multiply +from app import add, is_even, reverse_string, multiply, divide class TestMath: @@ -12,7 +12,9 @@ def test_add_positive(self): def test_multiply(self): assert multiply(9, 9) == 81 - + def test_divide(self): + assert divide(100, 10) == 10 + def test_add_negative(self): assert add(-1, -1) == -2 From 7ed5a73209acabc04c0b842674313e707456f96e Mon Sep 17 00:00:00 2001 From: jeetsondbritto <168982992+jeetsondbritto@users.noreply.github.com> Date: Tue, 3 Feb 2026 15:07:07 -0500 Subject: [PATCH 5/7] Add AI code review script and PR workflow --- .github/workflows/pr-review.yml | 56 +++++++++++++++++++++++++++++++++ requirements.txt | 2 +- scripts/ai_review.py | 46 +++++++++++++++++++++++++++ scripts/sample_diff.txt | 17 ++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/pr-review.yml create mode 100644 scripts/ai_review.py create mode 100644 scripts/sample_diff.txt diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml new file mode 100644 index 00000000..1bbebca3 --- /dev/null +++ b/.github/workflows/pr-review.yml @@ -0,0 +1,56 @@ +name: AI Code Review + +on: + pull_request: + branches: [main] + +permissions: + contents: read + pull-requests: write + +jobs: + review: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Get PR diff + run: | + git diff origin/main...HEAD > pr_diff.txt + + - name: Run AI review + id: ai-review + env: + GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} + run: | + REVIEW=$(python scripts/ai_review.py pr_diff.txt) + echo "review<> $GITHUB_OUTPUT + echo "$REVIEW" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Post review comment + uses: actions/github-script@v7 + env: + REVIEW: ${{ steps.ai-review.outputs.review }} + with: + script: | + const review = process.env.REVIEW; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: `## 🤖 AI Code Review\n\n${review}\n\n---\n*Powered by Gemini AI*` + }); diff --git a/requirements.txt b/requirements.txt index 5f456517..245709a3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Production dependencies (none for this simple app) - +google-genai>=1.0.0 # Development/testing dependencies pytest>=7.0.0 build>=1.0.0 diff --git a/scripts/ai_review.py b/scripts/ai_review.py new file mode 100644 index 00000000..4eabe64e --- /dev/null +++ b/scripts/ai_review.py @@ -0,0 +1,46 @@ +from google import genai +import sys + + +client = genai.Client() + +def review_code(diff_text): + """Send a code diff to Gemini for review.""" + prompt = f"""You are an expert code reviewer. Review the following code diff and provide feedback. + +Focus on: +1. Security vulnerabilities +2. Bug risks +3. Performance issues +4. Best practice violations + +For each issue found, provide: +- Severity: HIGH / MEDIUM / LOW +- Description of the issue +- Suggested fix + +If the code looks good, say so. + +Code diff to review: + +{diff_text} + + +Provide your review in a clear, structured format.""" + + response = client.models.generate_content( + model="gemini-2.5-flash", contents=prompt + ) + return response.text + + if __name__ == "__main__": + if len(sys.argv) > 1: + diff_file = sys.argv[1] + with open(diff_file, "r") as f: + diff_content = f.read() + else: + diff_content = sys.stdin.read() + + review = review_code(diff_content) + print(review) + \ No newline at end of file diff --git a/scripts/sample_diff.txt b/scripts/sample_diff.txt new file mode 100644 index 00000000..d4b5984b --- /dev/null +++ b/scripts/sample_diff.txt @@ -0,0 +1,17 @@ +diff --git a/app.py b/app.py +index 1234567..abcdefg 100644 +--- a/app.py ++++ b/app.py +@@ -1,5 +1,12 @@ + """Simple utility functions""" + ++import sqlite3 ++ ++def get_user(username): ++ conn = sqlite3.connect("users.db") ++ query = f"SELECT * FROM users WHERE name = '{username}'" ++ return conn.execute(query).fetchone() ++ + def add(a: int, b: int) -> int: + """Add two numbers together.""" + return a + b From 0c7321a34793a6670481443af7a770ff780077c4 Mon Sep 17 00:00:00 2001 From: jeetsondbritto <168982992+jeetsondbritto@users.noreply.github.com> Date: Tue, 3 Feb 2026 15:14:23 -0500 Subject: [PATCH 6/7] Add command execution feature --- dangerous.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 dangerous.py diff --git a/dangerous.py b/dangerous.py new file mode 100644 index 00000000..5d477bcb --- /dev/null +++ b/dangerous.py @@ -0,0 +1,7 @@ +import subprocess + +def run_command(user_input): + """Run a shell command from user input.""" + subprocess.call(user_input, shell=True) + +API_KEY = "sk-live-abc123def456" From ce4ba9ff1a517ce2261a311d6decdbe0896a2cdd Mon Sep 17 00:00:00 2001 From: jeetsondbritto <168982992+jeetsondbritto@users.noreply.github.com> Date: Tue, 3 Feb 2026 15:24:23 -0500 Subject: [PATCH 7/7] Add command execution feature --- dangerous.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dangerous.py b/dangerous.py index 5d477bcb..183ff101 100644 --- a/dangerous.py +++ b/dangerous.py @@ -4,4 +4,4 @@ def run_command(user_input): """Run a shell command from user input.""" subprocess.call(user_input, shell=True) -API_KEY = "sk-live-abc123def456" +API_KEY = "sk-live-abc123def476"