Skip to content

Commit 1de8893

Browse files
authored
Merge pull request #262 from DevanshuNEU/chore/ci-quality-gates
chore: enforce CI quality gates -- flake8 blocks, ESLint added, security blocks (OPE-55)
2 parents 27643fb + 6c75af1 commit 1de8893

30 files changed

Lines changed: 319 additions & 89 deletions

.github/workflows/ci.yml

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,28 @@ jobs:
3434
needs: changes
3535
if: ${{ needs.changes.outputs.backend == 'true' }}
3636
runs-on: ubuntu-latest
37-
37+
3838
steps:
3939
- uses: actions/checkout@v4
40-
40+
4141
- name: Set up Python
4242
uses: actions/setup-python@v5
4343
with:
4444
python-version: '3.11'
4545
cache: 'pip'
46-
46+
4747
- name: Install dependencies
4848
working-directory: ./backend
4949
run: |
5050
python -m pip install --upgrade pip
51-
pip install pytest pytest-cov httpx
51+
pip install pytest pytest-cov httpx flake8
5252
pip install -r requirements.txt
53-
53+
54+
- name: Lint (flake8)
55+
working-directory: ./backend
56+
run: |
57+
flake8 services/ routes/ middleware/ config/ dependencies.py main.py
58+
5459
- name: Run tests
5560
working-directory: ./backend
5661
env:
@@ -64,64 +69,63 @@ jobs:
6469
PINECONE_INDEX_NAME: "codeintel-test"
6570
run: |
6671
pytest tests/ -v --cov=services --cov-report=term-missing
67-
68-
- name: Check code quality
69-
working-directory: ./backend
70-
run: |
71-
pip install flake8
72-
flake8 services/ --max-line-length=120 --ignore=E501,W503 || true
7372
7473
test-frontend:
7574
name: Frontend Tests
7675
needs: changes
7776
if: ${{ needs.changes.outputs.frontend == 'true' }}
7877
runs-on: ubuntu-latest
79-
78+
8079
steps:
8180
- uses: actions/checkout@v4
82-
81+
8382
- name: Set up Bun
8483
uses: oven-sh/setup-bun@v2
8584
with:
8685
bun-version: latest
87-
86+
8887
- name: Install dependencies
8988
working-directory: ./frontend
9089
run: bun install
91-
90+
91+
- name: Lint (ESLint)
92+
working-directory: ./frontend
93+
run: bun run lint
94+
95+
- name: Check TypeScript
96+
working-directory: ./frontend
97+
run: bun run tsc --noEmit
98+
9299
- name: Build frontend
93100
working-directory: ./frontend
94101
run: bun run build
95-
102+
96103
- name: Run tests
97104
working-directory: ./frontend
98105
run: bun run test
99-
100-
- name: Check TypeScript
101-
working-directory: ./frontend
102-
run: bun run tsc --noEmit
103106

104107
security-scan:
105108
name: Security Scan
109+
needs: changes
110+
if: ${{ needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' }}
106111
runs-on: ubuntu-latest
107-
continue-on-error: true
108-
112+
109113
steps:
110114
- uses: actions/checkout@v4
111115
with:
112116
fetch-depth: 0
113-
117+
114118
- name: Run Trivy vulnerability scanner
115119
uses: aquasecurity/trivy-action@master
116120
with:
117121
scan-type: 'fs'
118122
scan-ref: '.'
119123
format: 'table'
120-
exit-code: '0'
121-
124+
severity: 'CRITICAL,HIGH'
125+
exit-code: '1'
126+
122127
- name: Check for secrets
123128
uses: trufflesecurity/trufflehog@main
124-
continue-on-error: true
125129
with:
126130
path: ./
127131
base: main

backend/.flake8

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[flake8]
2+
max-line-length = 120
3+
4+
# Only check for real bugs, not style.
5+
# F = pyflakes (unused imports, undefined names, shadowed vars)
6+
# E9 = runtime errors (syntax errors, indentation)
7+
# W6 = deprecated features
8+
# Style codes (E1/E2/E3/E5/W1/W2/W3/W5) are intentionally excluded.
9+
select = E9,F,W6
10+
11+
# Directories to skip
12+
exclude =
13+
.git,
14+
__pycache__,
15+
.venv,
16+
venv,
17+
repos,
18+
scripts,
19+
migrations
20+
21+
# Per-file ignores
22+
per-file-ignores =
23+
# main.py loads dotenv before imports (intentional)
24+
main.py:E402
25+
# __init__.py often has unused imports for re-export
26+
__init__.py:F401

backend/dependencies.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
All route modules import from here to avoid circular imports.
44
"""
55
from typing import Optional
6-
from fastapi import HTTPException, Depends
6+
from fastapi import HTTPException
77

88
from services.indexer_optimized import OptimizedCodeIndexer
99
from services.repo_manager import RepositoryManager
@@ -13,10 +13,10 @@
1313
from services.dna_extractor import DNAExtractor
1414
from services.rate_limiter import RateLimiter, APIKeyManager
1515
from services.supabase_service import get_supabase_service
16-
from services.input_validator import InputValidator, CostController
17-
from services.user_limits import init_user_limits_service, get_user_limits_service
16+
from services.input_validator import CostController
17+
from services.user_limits import init_user_limits_service
1818
from services.repo_validator import get_repo_validator
19-
from services.observability import metrics
19+
from services.observability import metrics # noqa: F401 -- re-exported for routes
2020

2121
# Service instances (singleton pattern)
2222
indexer = OptimizedCodeIndexer()

backend/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
init_sentry()
2020

2121
# Import API config (single source of truth for versioning)
22-
from config.api import API_PREFIX, API_VERSION
22+
from config.api import API_PREFIX
2323
from config.startup_checks import validate_environment
2424

2525
# Import routers

backend/routes/auth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Authentication Routes
33
Handles user signup, login, and session management
44
"""
5-
from fastapi import APIRouter, HTTPException, Depends, status
5+
from fastapi import APIRouter, HTTPException, Depends
66
from pydantic import BaseModel, EmailStr
77
from typing import Optional, Dict, Any
88
from services.auth import get_auth_service

backend/routes/github.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import secrets
1111
import httpx
1212
from fastapi import APIRouter, HTTPException, Depends, Query
13-
from fastapi.responses import RedirectResponse
1413
from typing import Optional
1514
from pydantic import BaseModel
1615
from urllib.parse import urlencode

backend/routes/repos.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ async def delete_repository(
159159
if not user_id:
160160
raise HTTPException(status_code=401, detail="User ID required")
161161

162-
# Verify ownership
163-
repo = get_repo_or_404(repo_id, user_id)
162+
# Verify ownership (raises 404 if not found)
163+
get_repo_or_404(repo_id, user_id)
164164

165165
try:
166166
success = repo_manager.delete_repo(repo_id)

backend/routes/search.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ async def explain_code(
135135
add_breadcrumb("Explain request received", category="explain", file_path=request.file_path)
136136

137137
try:
138-
repo = get_repo_or_404(request.repo_id, auth.user_id)
138+
get_repo_or_404(request.repo_id, auth.user_id)
139139

140140
logger.info(
141141
"Generating code explanation",

backend/routes/ws_playground.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
"""
1010
import json
1111
import asyncio
12-
from typing import Optional
1312

1413
from fastapi import WebSocket, WebSocketDisconnect
1514

backend/services/auth.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from typing import Optional, Dict, Any
77
import os
88
import jwt as pyjwt
9-
from datetime import datetime
109
from supabase import create_client, Client
1110

1211
from services.observability import logger

0 commit comments

Comments
 (0)