Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 30 additions & 26 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,28 @@ jobs:
needs: changes
if: ${{ needs.changes.outputs.backend == 'true' }}
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install dependencies
working-directory: ./backend
run: |
python -m pip install --upgrade pip
pip install pytest pytest-cov httpx
pip install pytest pytest-cov httpx flake8
pip install -r requirements.txt


- name: Lint (flake8)
working-directory: ./backend
run: |
flake8 services/ routes/ middleware/ config/ dependencies.py main.py

- name: Run tests
working-directory: ./backend
env:
Expand All @@ -64,64 +69,63 @@ jobs:
PINECONE_INDEX_NAME: "codeintel-test"
run: |
pytest tests/ -v --cov=services --cov-report=term-missing

- name: Check code quality
working-directory: ./backend
run: |
pip install flake8
flake8 services/ --max-line-length=120 --ignore=E501,W503 || true

test-frontend:
name: Frontend Tests
needs: changes
if: ${{ needs.changes.outputs.frontend == 'true' }}
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
working-directory: ./frontend
run: bun install


- name: Lint (ESLint)
working-directory: ./frontend
run: bun run lint

- name: Check TypeScript
working-directory: ./frontend
run: bun run tsc --noEmit

- name: Build frontend
working-directory: ./frontend
run: bun run build

- name: Run tests
working-directory: ./frontend
run: bun run test

- name: Check TypeScript
working-directory: ./frontend
run: bun run tsc --noEmit

security-scan:
name: Security Scan
needs: changes
if: ${{ needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' }}
Comment thread
DevanshuNEU marked this conversation as resolved.
runs-on: ubuntu-latest
continue-on-error: true


steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'table'
exit-code: '0'

severity: 'CRITICAL,HIGH'
exit-code: '1'

- name: Check for secrets
uses: trufflesecurity/trufflehog@main
continue-on-error: true
with:
path: ./
base: main
Expand Down
26 changes: 26 additions & 0 deletions backend/.flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[flake8]
max-line-length = 120
Comment thread
DevanshuNEU marked this conversation as resolved.

# Only check for real bugs, not style.
# F = pyflakes (unused imports, undefined names, shadowed vars)
# E9 = runtime errors (syntax errors, indentation)
# W6 = deprecated features
# Style codes (E1/E2/E3/E5/W1/W2/W3/W5) are intentionally excluded.
select = E9,F,W6

# Directories to skip
exclude =
.git,
__pycache__,
.venv,
venv,
repos,
scripts,
migrations

# Per-file ignores
per-file-ignores =
# main.py loads dotenv before imports (intentional)
main.py:E402
# __init__.py often has unused imports for re-export
__init__.py:F401
8 changes: 4 additions & 4 deletions backend/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
All route modules import from here to avoid circular imports.
"""
from typing import Optional
from fastapi import HTTPException, Depends
from fastapi import HTTPException

from services.indexer_optimized import OptimizedCodeIndexer
from services.repo_manager import RepositoryManager
Expand All @@ -13,10 +13,10 @@
from services.dna_extractor import DNAExtractor
from services.rate_limiter import RateLimiter, APIKeyManager
from services.supabase_service import get_supabase_service
from services.input_validator import InputValidator, CostController
from services.user_limits import init_user_limits_service, get_user_limits_service
from services.input_validator import CostController
from services.user_limits import init_user_limits_service
from services.repo_validator import get_repo_validator
from services.observability import metrics
from services.observability import metrics # noqa: F401 -- re-exported for routes

# Service instances (singleton pattern)
indexer = OptimizedCodeIndexer()
Expand Down
2 changes: 1 addition & 1 deletion backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
init_sentry()

# Import API config (single source of truth for versioning)
from config.api import API_PREFIX, API_VERSION
from config.api import API_PREFIX
from config.startup_checks import validate_environment

# Import routers
Expand Down
2 changes: 1 addition & 1 deletion backend/routes/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Authentication Routes
Handles user signup, login, and session management
"""
from fastapi import APIRouter, HTTPException, Depends, status
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel, EmailStr
from typing import Optional, Dict, Any
from services.auth import get_auth_service
Expand Down
1 change: 0 additions & 1 deletion backend/routes/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import secrets
import httpx
from fastapi import APIRouter, HTTPException, Depends, Query
from fastapi.responses import RedirectResponse
from typing import Optional
from pydantic import BaseModel
from urllib.parse import urlencode
Expand Down
4 changes: 2 additions & 2 deletions backend/routes/repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ async def delete_repository(
if not user_id:
raise HTTPException(status_code=401, detail="User ID required")

# Verify ownership
repo = get_repo_or_404(repo_id, user_id)
# Verify ownership (raises 404 if not found)
get_repo_or_404(repo_id, user_id)

try:
success = repo_manager.delete_repo(repo_id)
Expand Down
2 changes: 1 addition & 1 deletion backend/routes/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ async def explain_code(
add_breadcrumb("Explain request received", category="explain", file_path=request.file_path)

try:
repo = get_repo_or_404(request.repo_id, auth.user_id)
get_repo_or_404(request.repo_id, auth.user_id)

logger.info(
"Generating code explanation",
Expand Down
1 change: 0 additions & 1 deletion backend/routes/ws_playground.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"""
import json
import asyncio
from typing import Optional

from fastapi import WebSocket, WebSocketDisconnect

Expand Down
1 change: 0 additions & 1 deletion backend/services/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from typing import Optional, Dict, Any
import os
import jwt as pyjwt
from datetime import datetime
from supabase import create_client, Client

from services.observability import logger
Expand Down
2 changes: 1 addition & 1 deletion backend/services/dependency_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import tree_sitter_javascript as tsjavascript
from tree_sitter import Language, Parser

from services.observability import logger, capture_exception, track_time, metrics
from services.observability import logger, metrics


class DependencyAnalyzer:
Expand Down
10 changes: 3 additions & 7 deletions backend/services/dna_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
Generates a DNA document that helps AI understand how to write consistent code.
"""
from pathlib import Path
from typing import Dict, List, Set, Optional, Any
from collections import defaultdict, Counter
from typing import Dict, List, Optional
from collections import Counter
from dataclasses import dataclass, field, asdict
import re
import json

import tree_sitter_python as tspython
import tree_sitter_javascript as tsjavascript
Expand Down Expand Up @@ -122,7 +121,7 @@ def to_dict(self) -> Dict:

def to_markdown(self) -> str:
"""Generate markdown DNA document for AI consumption"""
md = f"# Codebase DNA\n\n"
md = "# Codebase DNA\n\n"

# Framework detection
if self.detected_framework:
Expand Down Expand Up @@ -823,9 +822,6 @@ def _extract_test_patterns(self, files: List[Path], repo_path: Path) -> TestPatt
conftest_files = list(repo_path.rglob('conftest.py'))
pattern.has_conftest = len(conftest_files) > 0

# Check for test directory structure
test_dirs = [d for d in ['tests', 'test'] if (repo_path / d).exists()]

for file_path in files:
try:
content = file_path.read_text(encoding='utf-8', errors='ignore')
Expand Down
7 changes: 0 additions & 7 deletions backend/services/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@

class AuthenticationError(Exception):
"""Base auth error. All auth exceptions inherit from this."""
pass


class TokenExpiredError(AuthenticationError):
"""JWT token has expired."""
pass


class InvalidTokenError(AuthenticationError):
"""JWT token is malformed, wrong signature, or invalid audience."""
pass


class TokenMissingClaimError(AuthenticationError):
Expand All @@ -31,19 +28,15 @@ def __init__(self, claim: str = "sub"):

class InvalidCredentialsError(AuthenticationError):
"""Login failed due to wrong email/password."""
pass


class SignupError(AuthenticationError):
"""User registration failed."""
pass


class SessionError(AuthenticationError):
"""Token refresh or logout failed."""
pass


class UserIdRequiredError(AuthenticationError):
"""Operation requires a user_id but auth context has None (e.g., API key without user)."""
pass
7 changes: 3 additions & 4 deletions backend/services/indexer_optimized.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@
"""
import os
from pathlib import Path
from typing import List, Dict, Optional, Tuple
from typing import List, Dict, Optional
import asyncio
from collections import defaultdict

from utils.test_detection import is_test_file, filter_test_files
from utils.test_detection import filter_test_files

# Tree-sitter for parsing
import tree_sitter_python as tspython
Expand All @@ -36,7 +35,7 @@
from services.search_v2 import TreeSitterExtractor, FunctionFilter, ExtractedFunction

# Observability
from services.observability import logger, trace_operation, track_time, capture_exception, add_breadcrumb, metrics
from services.observability import logger, track_time, capture_exception, add_breadcrumb, metrics

# Configuration
# Note: If using existing Pinecone index, match the dimension (1536 for small, 3072 for large)
Expand Down
2 changes: 1 addition & 1 deletion backend/services/indexing_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Entity can be job_id (playground) or repo_id (dashboard).
"""
import json
from typing import Optional, Any
from typing import Optional
from enum import Enum
from dataclasses import dataclass, asdict

Expand Down
1 change: 0 additions & 1 deletion backend/services/input_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"""
from typing import Optional, Set
from urllib.parse import urlparse
from pathlib import Path, PurePosixPath
import re
import os
import ipaddress
Expand Down
2 changes: 1 addition & 1 deletion backend/services/rate_limiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
import time
from typing import Optional, Dict, Callable
from datetime import datetime, timedelta
from datetime import datetime
from functools import wraps
import hashlib
import secrets
Expand Down
5 changes: 2 additions & 3 deletions backend/services/repo_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
Handles repository CRUD operations with PostgreSQL via Supabase
"""
import uuid
from typing import Dict, List, Optional
import os
from typing import List, Optional
import git
from pathlib import Path
from services.supabase_service import get_supabase_service
from services.observability import logger, capture_exception, metrics
from services.observability import logger, metrics


class RepositoryManager:
Expand Down
2 changes: 1 addition & 1 deletion backend/services/search_enhancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
rich embeddings, and hybrid search techniques.
"""
import re
from typing import List, Dict, Optional
from typing import List, Dict
from openai import AsyncOpenAI
import os

Expand Down
3 changes: 1 addition & 2 deletions backend/services/search_v2/summary_generator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Generate concise summaries for functions using GPT-4o-mini."""
import asyncio
from typing import List, Optional
from typing import List
from openai import AsyncOpenAI

from services.search_v2.types import ExtractedFunction
Expand Down
Loading