Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
5be70a6
python module package for handling broken imports and inconsistency
Apr 22, 2026
e1ee129
conecting my sever to openai
Apr 22, 2026
cc23674
github actions
Apr 22, 2026
a262d1c
analyzing every file in the github repository and identifies differen…
Apr 23, 2026
0bce8e1
contains parser which parses through every file to identify language …
Apr 23, 2026
37fe3a3
adding more features on the expected reports
Apr 23, 2026
59dbaa2
added more files to be parsed
Apr 23, 2026
6ebfa90
github actions, cloning repos, navigating through branches, pull requ…
Apr 27, 2026
8d8407e
my FASTAPI used for GET and POST request
Apr 27, 2026
4ab0c1d
virtual environment
Apr 27, 2026
b2a4f09
main functions of the code reviews
Apr 27, 2026
3b237bf
my FASTAPI used for GET and POST request
Apr 27, 2026
de37db6
analyzing larger files, empty files and return issues
Apr 27, 2026
a75a3ef
analyzing go files
Apr 27, 2026
84b47b3
analyzing python files
Apr 27, 2026
7e66bd2
analyzer executable files
Apr 27, 2026
cb2fca0
utils executable files
Apr 27, 2026
54019ca
analyzing different types of files inside a repo
Apr 27, 2026
0236e51
github actions, cloning repos, navigating through branches, pull requ…
Apr 27, 2026
822588c
main functions of the code reviews
Apr 27, 2026
5156762
updated doctstring, and optimizing time taken for analyzing bigger repos
Apr 27, 2026
2681506
added docstring to make the program self documenting
Apr 27, 2026
634449c
added doctstring and code optimization
Apr 27, 2026
316ad95
updated docstring and code optimization for faster analysis
Apr 27, 2026
32b844c
Remove file
Apr 27, 2026
7ec926d
optimizing time for clonining github repos
Apr 27, 2026
d90bb64
updated docstring and code optimization for faster analysis
Apr 27, 2026
4a9c299
removing ai folder
Apr 27, 2026
ac81ddb
updated docstring and code optimization for faster analysis
Apr 27, 2026
a174c10
handling authentication of users
Apr 27, 2026
e34e826
required modules for the project
Apr 27, 2026
460d991
frontend part of the project rendering user interface
Apr 27, 2026
81ef6c7
optimized cloning repos without taking too much time
Apr 27, 2026
beab142
analyzing file difference in the pull requests
Apr 27, 2026
f01f413
updating changes on the light mode theme and font colours
Apr 27, 2026
4a13f6a
caching analysis results by commit SHA
Apr 27, 2026
3523d3e
enabling downloads of the report in pdf or JSON format
Apr 27, 2026
c58e607
updated parser function
Apr 27, 2026
42f3d32
updating websocket endpoint to show progress
Apr 27, 2026
51837b3
keeping history after login
Apr 27, 2026
9d47a82
apdated exporting PDF and JSON reports
Apr 27, 2026
c0b1481
Added listing of github issues in the repository
Apr 28, 2026
7115ad7
added bash detection
Apr 28, 2026
e1179be
updated github issues detection
Apr 28, 2026
c25ee45
adjusting positioning of branches and tags in the ui
Apr 28, 2026
1125eb9
updated caching of github issues
Apr 28, 2026
5ac7915
added bash on the list of files to be detected
Apr 28, 2026
091e28c
updated time for cloning repository to be short
Apr 28, 2026
3a0fc00
listing all my endpoints
Apr 28, 2026
abd819d
updated issues detection
Apr 28, 2026
753900c
added bash, html, css, detection
Apr 28, 2026
c4a1231
Added listing of github issues, css, html detection in the repository
Apr 28, 2026
ec7c992
added dockerfile detection
Apr 28, 2026
6867d82
updated detect_language function to correctly detect css, html and ba…
Apr 28, 2026
1ab31d3
updated colaboration page and analytics page
Apr 28, 2026
ac86529
added collaboration and analytics
Apr 28, 2026
40279f7
added collaboration page to allow users share their reports
Apr 28, 2026
09ffeb2
Remove folder_name
mlizlent May 3, 2026
03137da
Merge branch 'main'
mlizlent May 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
43 changes: 43 additions & 0 deletions .github/workflows/code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: PR Code Reviewer

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
review:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: pip install gitpython openai

- name: Get changed files
run: git diff --name-only origin/main > changed.txt

- name: Run reviewer
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: python main.py > report.txt

- name: Comment PR
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('report.txt', 'utf8');

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: report
});
246 changes: 246 additions & 0 deletions ENDPOINTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
# API Endpoints

Base URL: `http://localhost:8000`

---

## Authentication

### `POST /register`
Create a new user account.

**Request:**
```json
{ "email": "user@example.com", "password": "yourpassword" }
```
**Response:**
```json
{ "token": "<jwt>", "email": "user@example.com" }
```
**Errors:** `400` — Email already registered.

---

### `POST /login`
Sign in and receive a JWT token.

**Request:**
```json
{ "email": "user@example.com", "password": "yourpassword" }
```
**Response:**
```json
{ "token": "<jwt>", "email": "user@example.com" }
```
**Errors:** `401` — Invalid email or password.

---

## Analysis

### `POST /analyze`
Analyze a GitHub repository. Saves to history if authenticated.

**Headers (optional):** `Authorization: Bearer <token>`

**Request:**
```json
{
"url": "https://github.com/user/repo",
"branch": "main",
"client_id": "client_abc123"
}
```
- `branch` — optional, defaults to repo default branch
- `client_id` — optional, used for WebSocket progress updates

**Response:**
```json
{
"repo_url": "...",
"branch": "main",
"branches": [...],
"meta": { "full_name": "...", "stars": 0, "forks": 0, ... },
"tags": [...],
"commits": [...],
"pull_requests": [...],
"issues": [...],
"summary": { "total": 0, "code": 0, "docs": 0, "other": 0, "issues": 0 },
"code": [...],
"docs": [...],
"other": [...]
}
```

---

### `POST /switch-branch`
Switch to a different branch and re-analyze files. Skips GitHub API calls.

**Request:**
```json
{ "url": "https://github.com/user/repo", "branch": "feature-x" }
```
**Response:** Same structure as `/analyze`

---

### `POST /branches`
Get all branches for a repository without full analysis.

**Request:**
```json
{ "url": "https://github.com/user/repo" }
```
**Response:**
```json
{
"branches": [
{ "name": "main", "is_default": true, "merged": true, "sha": "abc1234" }
]
}
```

---

### `POST /analyze/pr-diff`
Analyze only the files changed in a pull request.

**Headers (optional):** `Authorization: Bearer <token>`

**Request:**
```json
{
"url": "https://github.com/user/repo",
"base_branch": "main",
"compare_branch": "feature-x",
"client_id": "client_abc123"
}
```
**Response:**
```json
{
"repo_url": "...",
"base_branch": "main",
"compare_branch": "feature-x",
"diff_stats": { "files_changed": 3, "insertions": 45, "deletions": 12 },
"summary": { "files_changed": 3, "code_files": 2, "issues": 5 },
"files": [...]
}
```

---

## History

### `GET /history`
Get analysis history for the authenticated user.

**Headers:** `Authorization: Bearer <token>`

**Response:**
```json
[
{
"id": "2024-01-01T00:00:00",
"repo_url": "https://github.com/user/repo",
"branch": "main",
"summary": { "total": 100, "code": 80, "docs": 10, "other": 10, "issues": 5 },
"meta": { ... }
}
]
```
Returns `[]` if not authenticated.

---

### `DELETE /history`
Clear all history for the authenticated user.

**Headers:** `Authorization: Bearer <token>`

**Response:**
```json
{ "status": "cleared" }
```

---

## Export

### `POST /export/json`
Export analysis report as a downloadable JSON file.

**Request:** Full analysis result object (from `/analyze` response)

**Response:** `application/json` file download — `analysis-report.json`

---

### `POST /export/pdf`
Export analysis report as a downloadable PDF file.

**Request:** Full analysis result object (from `/analyze` response)

**Response:** `application/pdf` file download — `analysis-report.pdf`

---

## Cache

### `DELETE /cache`
Clear all cached file analysis results.

**Response:**
```json
{ "status": "cache cleared" }
```

---

## WebSocket

### `WS /ws/{client_id}`
Real-time progress updates during analysis.

**Connect:** `ws://localhost:8000/ws/<client_id>`

**Messages received:**
```json
{ "stage": "cloning", "message": "Cloning repository...", "progress": 0 }
{ "stage": "scanning", "message": "Found 1234 files...", "progress": 5 }
{ "stage": "analyzing", "message": "Analyzing... 500/1234", "progress": 45, "total": 1234, "completed": 500 }
{ "stage": "fetching", "message": "Fetching repository metadata...", "progress": 90 }
{ "stage": "complete", "message": "Analysis complete!", "progress": 100 }
```

---

## Other

### `GET /`
Serve the frontend HTML page.

### `GET /health`
Health check.

**Response:**
```json
{ "status": "ok" }
```

---

## Authentication Notes

- JWT tokens expire after **30 days**
- Pass token as: `Authorization: Bearer <token>`
- All auth-required endpoints return empty/no-op if token is missing (guest mode)
- Set `JWT_SECRET` env var for persistent sessions across server restarts

## Rate Limiting

GitHub API is used without a token (60 requests/hour limit). For heavy usage, set:
```bash
export GITHUB_TOKEN="your_token"
```
12 changes: 12 additions & 0 deletions analyzer/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from .python_analyzer import PythonAnalyzer
from .go_analyzer import GoAnalyzer
from .generic import GenericAnalyzer

def get_analyzer(language):
"""Return appropriate analyzer instance based on detected language."""
if language == "python":
return PythonAnalyzer()
elif language == "go":
return GoAnalyzer()
else:
return GenericAnalyzer()
Binary file added analyzer/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file added analyzer/__pycache__/base.cpython-312.pyc
Binary file not shown.
Binary file added analyzer/__pycache__/detector.cpython-312.pyc
Binary file not shown.
Binary file added analyzer/__pycache__/generic.cpython-312.pyc
Binary file not shown.
Binary file added analyzer/__pycache__/github.cpython-312.pyc
Binary file not shown.
Binary file added analyzer/__pycache__/go_analyzer.cpython-312.pyc
Binary file not shown.
Binary file not shown.
74 changes: 74 additions & 0 deletions analyzer/detector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import os

EXTENSION_MAP = {
".py": "python",
".ipynb": "python",
".go": "go",
".js": "javascript",
".ts": "typescript",
".java": "java",
".cpp": "cpp",
".c": "c",
".rs": "rust",
".php": "php",
".rb": "ruby",
".kt": "kotlin",
".swift": "swift",
".sh": "bash",
".bash": "bash",
".zsh": "bash",
".html": "html",
".htm": "html",
".css": "css",
}

SPECIAL_FILES = {
"Dockerfile": "docker",
"dockerfile": "docker",
"Makefile": "make",
"CMakeLists.txt": "cmake",
}


def detect_language(file_path, ext_hint: str = ""):
"""Detect programming language from file path and content."""
filename = os.path.basename(file_path)

# Layer 1: special filenames
if filename in SPECIAL_FILES:
return SPECIAL_FILES[filename]

# Layer 2: use pre-computed ext hint if provided, else extract from path
ext = (ext_hint or os.path.splitext(file_path)[1]).lower()
if ext in EXTENSION_MAP:
return EXTENSION_MAP[ext]

# Layer 3: content-based fallback
return detect_by_content(file_path)


def detect_by_content(file_path):
"""Fallback language detection by analyzing file content."""
try:
# Only read first 512 bytes for speed
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
content = f.read(512)

# Quick substring checks (faster than regex)
if "package main" in content or "func main()" in content:
return "go"
if content.startswith("#!/bin/bash") or content.startswith("#!/bin/sh") or content.startswith("#!/usr/bin/env bash"):
return "bash"
if "def " in content or "import " in content:
return "python"
if "public class" in content or "private class" in content:
return "java"
if "console.log" in content or "function(" in content:
return "javascript"
if "#include" in content:
return "cpp"

except:
pass

return "unknown"
Loading
Loading