From 71061e30d8c2fde9831e99327fc07dd4463b67a6 Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:03:34 +0300 Subject: [PATCH 01/13] Add multiply function, tests, and CI workflow --- .github/workflows/ci.yml | 26 ++++++++++++++++++++++++++ app.py | 4 ++++ tests/test_app.py | 18 +++++++++++++++++- 3 files changed, 47 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..6fffa848 100644 --- a/app.py +++ b/app.py @@ -14,3 +14,7 @@ def is_even(n: int) -> bool: def reverse_string(s: str) -> str: """Reverse a string.""" return s[::-1] + +def multiply(a: int, b: int) -> int: + """Multiply two numbers together.""" + return a * b diff --git a/tests/test_app.py b/tests/test_app.py index 79c3e093..04981b6d 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: @@ -22,3 +22,19 @@ def test_reverse(self): def test_is_even(self): assert is_even(4) is True assert is_even(3) is False + +class TestMultiply: + """Tests for the multiply function.""" + + def test_multiply_positive_numbers(self): + """Test multiplying two positive numbers.""" + assert multiply(3, 4) == 12 + + def test_multiply_by_zero(self): + """Test multiplying by zero.""" + assert multiply(5, 0) == 0 + + def test_multiply_negative_numbers(self): + """Test multiplying negative numbers.""" + assert multiply(-2, 3) == -6 + From cc5014ef1c45d967a3b2184edf6dee3349baa84b Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:04:20 +0300 Subject: [PATCH 02/13] Trigger workflow From 808a9c66cc0c93af4cb45dd89a975d9d655bba02 Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:05:19 +0300 Subject: [PATCH 03/13] Trigger workflow From 190835672aea3a548d7b4e58cb4cac164532f18c Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:06:51 +0300 Subject: [PATCH 04/13] Break a test --- tests/test_app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_app.py b/tests/test_app.py index 04981b6d..899e039e 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -26,9 +26,9 @@ def test_is_even(self): class TestMultiply: """Tests for the multiply function.""" - def test_multiply_positive_numbers(self): - """Test multiplying two positive numbers.""" - assert multiply(3, 4) == 12 + def test_multiple(self): + """Test multiplying two positive numbers.""" + assert multiply(9, 9) == 18 # This is wrong! def test_multiply_by_zero(self): """Test multiplying by zero.""" From 108ee0fc25488884ac202948303e3bfc1307e54a Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:10:31 +0300 Subject: [PATCH 05/13] 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 899e039e..8dfd325f 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -28,7 +28,7 @@ class TestMultiply: def test_multiple(self): """Test multiplying two positive numbers.""" - assert multiply(9, 9) == 18 # This is wrong! + assert multiply(9, 9) == 81 def test_multiply_by_zero(self): """Test multiplying by zero.""" From 4b40c3f965b2e46878e43baf9b26e437bb0e72ca Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:12:27 +0300 Subject: [PATCH 06/13] Fix the test --- tests/test_app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_app.py b/tests/test_app.py index 8dfd325f..09922fcb 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -30,6 +30,7 @@ def test_multiple(self): """Test multiplying two positive numbers.""" assert multiply(9, 9) == 81 + def test_multiply_by_zero(self): """Test multiplying by zero.""" assert multiply(5, 0) == 0 From 308dd6d5e5364f7316225b812c7470343185ee72 Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:16:01 +0300 Subject: [PATCH 07/13] Fix the test --- tests/test_app.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_app.py b/tests/test_app.py index 09922fcb..de165daa 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -27,9 +27,10 @@ class TestMultiply: """Tests for the multiply function.""" def test_multiple(self): - """Test multiplying two positive numbers.""" - assert multiply(9, 9) == 81 - + """Test multiplying two positive numbers.""" + assert multiply(9, 9) == 81 + + def test_multiply_by_zero(self): """Test multiplying by zero.""" From 8e015eb44568840b927eef2e23623346904eb611 Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:30:25 +0300 Subject: [PATCH 08/13] Add build and artifact upload to CI --- .github/workflows/ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0863fdd..4b71749b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,15 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Build package + run: python -m build + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: python-package + path: dist/ + - name: Set up Python uses: actions/setup-python@v5 with: From 29cc2c08cd29db02eb20c9b560c6be3d9bb206a2 Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:31:35 +0300 Subject: [PATCH 09/13] Add build and artifact upload to CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b71749b..de884c4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Build package + - name: Build package run: python -m build - name: Upload artifact From 97c8a2db708fd42e9facfb28a279b2cdc13bc6be Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:34:34 +0300 Subject: [PATCH 10/13] Add build and artifact upload to CI --- .github/workflows/ci.yml | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de884c4e..afceae69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,17 @@ jobs: - 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 + - name: Build package run: python -m build @@ -22,14 +33,16 @@ jobs: with: name: python-package path: dist/ +``` - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' +**Key changes:** - - name: Install dependencies - run: pip install -r requirements.txt +1. **Set up Python first** - You need Python installed before you can run any Python commands +2. **Install dependencies** - This includes pytest and any build tools +3. **Run tests** - Verify everything works before building +4. **Build package** - Only build if tests pass +5. **Upload artifact** - Upload the built package - - name: Run tests - run: pytest -v +**Additional note:** You'll also need to make sure the `build` package is installed. Add it to your `requirements.txt`: +``` +build \ No newline at end of file From 4a571b2f555843569a371f0ba37aaee54888a645 Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:36:25 +0300 Subject: [PATCH 11/13] Add build and artifact upload to CI --- .github/workflows/ci.yml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afceae69..8bd847cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - name: Run tests run: pytest -v - - name: Build package + - name: Build package run: python -m build - name: Upload artifact @@ -33,16 +33,3 @@ jobs: with: name: python-package path: dist/ -``` - -**Key changes:** - -1. **Set up Python first** - You need Python installed before you can run any Python commands -2. **Install dependencies** - This includes pytest and any build tools -3. **Run tests** - Verify everything works before building -4. **Build package** - Only build if tests pass -5. **Upload artifact** - Upload the built package - -**Additional note:** You'll also need to make sure the `build` package is installed. Add it to your `requirements.txt`: -``` -build \ No newline at end of file From 234c6d2362141f3950d88d295580e806e1f7e4bf Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Sat, 7 Feb 2026 14:37:19 +0300 Subject: [PATCH 12/13] Add build and artifact upload to CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8bd847cf..873f6ae2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - name: Run tests run: pytest -v - - name: Build package + - name: Build package run: python -m build - name: Upload artifact From be1b4664312bb534a8bcd9891058225095cad395 Mon Sep 17 00:00:00 2001 From: Cydo73 Date: Mon, 9 Feb 2026 15:24:51 +0300 Subject: [PATCH 13/13] Add AI code review script and PR workflow --- .github/workflows/pr-review.yml | 56 +++++++++++++++++++++++ .gitignore | 6 +++ requirements.txt | 6 ++- scripts/ai_review.py | 78 +++++++++++++++++++++++++++++++++ scripts/sample_diff.txt | 17 +++++++ test_mods.py | 36 +++++++++++++++ 6 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/pr-review.yml create mode 100644 scripts/ai_review.py create mode 100644 scripts/sample_diff.txt create mode 100644 test_mods.py 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/.gitignore b/.gitignore index ce1e9555..2d333894 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,12 @@ venv/ env/ .venv/ +# Environment variables +.env +venv/ +__pycache__/ +*.pyc + # Distribution / packaging dist/ build/ diff --git a/requirements.txt b/requirements.txt index 5f456517..5d5d5f7b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,7 @@ -# Production dependencies (none for this simple app) +# Production dependencies +requests>=2.31.0 +python-dotenv>=1.0.0 # Development/testing dependencies pytest>=7.0.0 -build>=1.0.0 +build>=1.0.0 \ No newline at end of file diff --git a/scripts/ai_review.py b/scripts/ai_review.py new file mode 100644 index 00000000..41fda33b --- /dev/null +++ b/scripts/ai_review.py @@ -0,0 +1,78 @@ +import requests +import sys +import os +import json +from dotenv import load_dotenv + +# Load environment +load_dotenv(override=True) +api_key = os.environ.get('GEMINI_API_KEY') + +if not api_key: + print("ERROR: GEMINI_API_KEY not found!") + sys.exit(1) + +api_key = api_key.strip() +print(f"API Key loaded: {api_key[:10]}...{api_key[-4:]}") + +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.""" + + # Use the correct model name from the list + url = f"https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent?key={api_key}" + + headers = { + 'Content-Type': 'application/json' + } + + data = { + "contents": [{ + "parts": [{ + "text": prompt + }] + }] + } + + print("Sending request to Gemini API...") + response = requests.post(url, headers=headers, json=data) + + if response.status_code != 200: + print(f"Error: {response.status_code}") + print(response.text) + sys.exit(1) + + result = response.json() + return result['candidates'][0]['content']['parts'][0]['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() + + print("\nGenerating review...\n") + review = review_code(diff_content) + print("\n=== CODE REVIEW ===\n") + 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 diff --git a/test_mods.py b/test_mods.py new file mode 100644 index 00000000..ba420824 --- /dev/null +++ b/test_mods.py @@ -0,0 +1,36 @@ +import requests +import os +from dotenv import load_dotenv + +load_dotenv(override=True) +api_key = os.environ.get('GEMINI_API_KEY').strip() + +print(f"API Key: {api_key[:10]}...{api_key[-4:]}") +print("\nChecking available models...\n") + +# Try v1 API +print("=== Trying v1 API ===") +url = f"https://generativelanguage.googleapis.com/v1/models?key={api_key}" +response = requests.get(url) +print(f"Status: {response.status_code}") +if response.status_code == 200: + models = response.json() + print("Available models:") + for model in models.get('models', []): + print(f" - {model.get('name')}") + print(f" Methods: {model.get('supportedGenerationMethods', [])}") +else: + print(response.text) + +print("\n=== Trying v1beta API ===") +url = f"https://generativelanguage.googleapis.com/v1beta/models?key={api_key}" +response = requests.get(url) +print(f"Status: {response.status_code}") +if response.status_code == 200: + models = response.json() + print("Available models:") + for model in models.get('models', []): + print(f" - {model.get('name')}") + print(f" Methods: {model.get('supportedGenerationMethods', [])}") +else: + print(response.text) \ No newline at end of file