|
1 | | -# pull-shark-test |
| 1 | +# 🤖 AutoPR Lab |
2 | 2 |
|
3 | | -Test 1 |
| 3 | +> **Sistema de revisión y merge automático de Pull Requests con análisis de seguridad integrado.** |
| 4 | +> Cero intervención humana. Reglas estrictas. Decisiones trazables. |
4 | 5 |
|
5 | | -Test 2 |
| 6 | +[](https://github.com/features/actions) |
| 7 | +[](https://python.org) |
| 8 | +[](LICENSE) |
| 9 | +[](docs/security.md) |
6 | 10 |
|
7 | | -Test 3 |
| 11 | +--- |
8 | 12 |
|
9 | | -Test 4 |
| 13 | +## ¿Qué es AutoPR Lab? |
10 | 14 |
|
11 | | -Test 5 |
| 15 | +AutoPR Lab es un sistema de **revisión automática de Pull Requests** construido sobre GitHub Actions y Python. Analiza cada PR en tiempo real, ejecuta detectores de seguridad modulares, y toma una de tres decisiones sin intervención humana: |
12 | 16 |
|
13 | | -Test 6 |
| 17 | +| Decisión | Condición | Acción | |
| 18 | +|----------|-----------|--------| |
| 19 | +| ✅ **MERGE** | Sin problemas | Aprueba + merge automático | |
| 20 | +| ⚠️ **WARN MERGE** | Solo advertencias | Aprueba + merge + comentario | |
| 21 | +| ❌ **REJECT** | Errores críticos | Comenta problemas + cierra PR | |
14 | 22 |
|
15 | | -Test 7 |
| 23 | +--- |
16 | 24 |
|
17 | | -Test 8 |
| 25 | +## 🏗️ Arquitectura del Proyecto |
18 | 26 |
|
19 | | -Test 9 |
| 27 | +``` |
| 28 | +AutoPR-Lab/ |
| 29 | +│ |
| 30 | +├── .github/ |
| 31 | +│ └── workflows/ |
| 32 | +│ └── auto-pr.yml # Workflow principal de GitHub Actions |
| 33 | +│ |
| 34 | +├── core/ |
| 35 | +│ ├── __init__.py |
| 36 | +│ └── scanner.py # Motor principal de análisis |
| 37 | +│ |
| 38 | +├── detectors/ |
| 39 | +│ ├── __init__.py # Auto-descubrimiento de detectores |
| 40 | +│ ├── base_detector.py # Clase base abstracta (contrato) |
| 41 | +│ ├── api_keys_detector.py # Detecta API keys y tokens |
| 42 | +│ ├── passwords_detector.py # Detecta passwords hardcodeados |
| 43 | +│ ├── sensitive_files_detector.py # Detecta archivos sensibles |
| 44 | +│ └── detector_validator.py # Valida estructura de detectores nuevos |
| 45 | +│ |
| 46 | +├── utils/ |
| 47 | +│ ├── __init__.py |
| 48 | +│ ├── github_api.py # Cliente de la GitHub REST API |
| 49 | +│ ├── comment_templates.py # Templates para comentarios del bot |
| 50 | +│ └── logger.py # Sistema de logging con colores |
| 51 | +│ |
| 52 | +├── scripts/ |
| 53 | +│ └── decision_engine.py # Entry point: orquesta todo el flujo |
| 54 | +│ |
| 55 | +├── tests/ |
| 56 | +│ ├── test_detectors.py # Tests unitarios de detectores |
| 57 | +│ └── test_scanner.py # Tests de integración del scanner |
| 58 | +│ |
| 59 | +├── docs/ |
| 60 | +│ ├── how-to-add-detector.md # Guía para contributors |
| 61 | +│ └── example-outputs.md # Ejemplos de outputs del sistema |
| 62 | +│ |
| 63 | +├── examples/ |
| 64 | +│ ├── valid-pr/ # Ejemplos de PRs que serán aceptados |
| 65 | +│ └── invalid-pr/ # Ejemplos de PRs que serán rechazados |
| 66 | +│ |
| 67 | +└── requirements.txt # Dependencias (solo stdlib de Python) |
| 68 | +``` |
20 | 69 |
|
21 | | -Test 10 |
| 70 | +--- |
22 | 71 |
|
23 | | -Test 11 |
| 72 | +## 🔍 Sistema de Detectores |
24 | 73 |
|
25 | | -Test 12 |
| 74 | +Los detectores son módulos **independientes** que analizan el código y devuelven resultados estandarizados: |
26 | 75 |
|
27 | | -Test 13 |
| 76 | +```python |
| 77 | +@dataclass |
| 78 | +class DetectorResult: |
| 79 | + status: DetectorStatus # OK | WARNING | ERROR |
| 80 | + detector_name: str |
| 81 | + message: str |
| 82 | + details: List[str] |
| 83 | + file_path: Optional[str] |
| 84 | + line_number: Optional[int] |
| 85 | +``` |
28 | 86 |
|
29 | | -Test 14 |
| 87 | +### Detectores incluidos |
30 | 88 |
|
31 | | -Test 15 |
| 89 | +| Detector | Qué detecta | Severidad | |
| 90 | +|----------|-------------|-----------| |
| 91 | +| `APIKeysDetector` | GitHub tokens, OpenAI keys, AWS secrets, claves RSA, URLs con credenciales | 🔴 Critical | |
| 92 | +| `PasswordsDetector` | Passwords hardcodeados, contraseñas triviales, tokens de autenticación | 🔴 Critical | |
| 93 | +| `SensitiveFilesDetector` | `.env`, `.pem`, `.key`, `credentials.json`, archivos de BD | 🔴 Critical | |
| 94 | +| `DetectorFormatValidator` | Estructura, imports prohibidos, `eval/exec`, herencia correcta | 🔴 Critical | |
| 95 | + |
| 96 | +--- |
| 97 | + |
| 98 | +## 🛡️ Reglas de Seguridad (Auto-Merge) |
| 99 | + |
| 100 | +El sistema solo permite merge automático cuando se cumplen **TODAS** estas condiciones: |
| 101 | + |
| 102 | +### ✅ Rutas permitidas para auto-merge |
| 103 | +``` |
| 104 | +detectors/ ← Nuevos detectores |
| 105 | +tests/ ← Tests |
| 106 | +docs/ ← Documentación |
| 107 | +examples/ ← Ejemplos |
| 108 | +README.md ← Readme principal |
| 109 | +``` |
| 110 | + |
| 111 | +### 🚫 Rutas siempre bloqueadas |
| 112 | +``` |
| 113 | +core/ ← Motor principal (requiere revisión manual) |
| 114 | +.github/workflows/ ← Workflows de CI/CD (crítico) |
| 115 | +scripts/ ← Scripts de decisión |
| 116 | +requirements.txt ← Dependencias |
| 117 | +pyproject.toml ← Configuración del proyecto |
| 118 | +Makefile ← Automatización |
| 119 | +``` |
| 120 | + |
| 121 | +### 📏 Límites de tamaño |
| 122 | +- Máximo **10 archivos** por PR |
| 123 | +- Máximo **500 líneas** cambiadas |
| 124 | + |
| 125 | +--- |
| 126 | + |
| 127 | +## ⚡ Cómo Funciona (Flujo Completo) |
| 128 | + |
| 129 | +``` |
| 130 | +PR Abierto/Actualizado |
| 131 | + │ |
| 132 | + ▼ |
| 133 | +┌─────────────────────────────────┐ |
| 134 | +│ GitHub Actions Trigger │ |
| 135 | +│ on: pull_request │ |
| 136 | +└─────────────┬───────────────────┘ |
| 137 | + │ |
| 138 | + ▼ |
| 139 | +┌─────────────────────────────────┐ |
| 140 | +│ decision_engine.py │ |
| 141 | +│ - Lee variables de entorno │ |
| 142 | +│ - Obtiene archivos del PR │ |
| 143 | +└─────────────┬───────────────────┘ |
| 144 | + │ |
| 145 | + ▼ |
| 146 | +┌─────────────────────────────────┐ |
| 147 | +│ SecurityRules.validate_paths │ |
| 148 | +│ - ¿Rutas permitidas? │ |
| 149 | +│ - ¿Tamaño dentro de límites? │ |
| 150 | +└─────────────┬───────────────────┘ |
| 151 | + │ |
| 152 | + ▼ |
| 153 | +┌─────────────────────────────────┐ |
| 154 | +│ Scanner.scan_pr │ |
| 155 | +│ - Ejecuta TODOS los │ |
| 156 | +│ detectores sobre cada │ |
| 157 | +│ archivo del PR │ |
| 158 | +└─────────────┬───────────────────┘ |
| 159 | + │ |
| 160 | + ┌─────────┼──────────┐ |
| 161 | + ▼ ▼ ▼ |
| 162 | + ERROR WARNING OK |
| 163 | + │ │ │ |
| 164 | + ▼ ▼ ▼ |
| 165 | + REJECT WARN_MERGE MERGE |
| 166 | + │ │ │ |
| 167 | + ▼ ▼ ▼ |
| 168 | +Comentar Aprobar Aprobar |
| 169 | + + Cerrar + Merge + Merge |
| 170 | + + Comentar |
| 171 | +``` |
| 172 | + |
| 173 | +--- |
| 174 | + |
| 175 | +## 🚀 Instalación y Configuración |
| 176 | + |
| 177 | +### 1. Fork o clona el repositorio |
| 178 | + |
| 179 | +```bash |
| 180 | +git clone https://github.com/devsebastian44/AutoPR-Lab.git |
| 181 | +cd AutoPR-Lab |
| 182 | +``` |
| 183 | + |
| 184 | +### 2. Habilitar GitHub Actions |
| 185 | + |
| 186 | +El workflow en `.github/workflows/auto-pr.yml` se activa automáticamente en cada PR. |
| 187 | + |
| 188 | +**No necesitas configurar nada adicional** — usa el `GITHUB_TOKEN` que GitHub provee automáticamente. |
| 189 | + |
| 190 | +### 3. Configurar permisos del repositorio |
| 191 | + |
| 192 | +En `Settings → Actions → General`: |
| 193 | +- Marcar **"Read and write permissions"** para el GITHUB_TOKEN |
| 194 | +- Marcar **"Allow GitHub Actions to create and approve pull requests"** |
| 195 | + |
| 196 | +### 4. Opcional: Ejecutar localmente |
| 197 | + |
| 198 | +```bash |
| 199 | +# Instalar dependencias (solo para desarrollo) |
| 200 | +pip install -r requirements.txt |
| 201 | + |
| 202 | +# Ejecutar tests |
| 203 | +python -m pytest tests/ -v |
| 204 | + |
| 205 | +# Dry run (sin ejecutar acciones reales en GitHub) |
| 206 | +export GITHUB_TOKEN="tu_token" |
| 207 | +export GITHUB_REPOSITORY="owner/repo" |
| 208 | +export PR_NUMBER="123" |
| 209 | +export DRY_RUN="true" |
| 210 | +python scripts/decision_engine.py |
| 211 | +``` |
| 212 | + |
| 213 | +--- |
| 214 | + |
| 215 | +## 🔌 Agregar un Detector Nuevo |
| 216 | + |
| 217 | +1. Crea `/detectors/mi_detector.py` heredando de `BaseDetector` |
| 218 | +2. Crea `/tests/test_mi_detector.py` con tests unitarios |
| 219 | +3. Abre un PR — **AutoPR Lab lo revisará y mergeará automáticamente** si está bien formado |
| 220 | + |
| 221 | +```python |
| 222 | +# detectors/mi_detector.py |
| 223 | +from detectors.base_detector import BaseDetector, DetectorResult, DetectorStatus |
| 224 | +from typing import List |
| 225 | + |
| 226 | +class MiDetector(BaseDetector): |
| 227 | + @property |
| 228 | + def name(self) -> str: |
| 229 | + return "MiDetector" |
| 230 | + |
| 231 | + @property |
| 232 | + def description(self) -> str: |
| 233 | + return "Detecta X en el código" |
| 234 | + |
| 235 | + @property |
| 236 | + def severity(self) -> str: |
| 237 | + return "high" # critical | high | medium | low |
| 238 | + |
| 239 | + def analyze(self, file_path: str, content: str) -> List[DetectorResult]: |
| 240 | + results = [] |
| 241 | + # Tu lógica aquí... |
| 242 | + return results |
| 243 | +``` |
| 244 | + |
| 245 | +Ver guía completa: [docs/how-to-add-detector.md](docs/how-to-add-detector.md) |
| 246 | + |
| 247 | +--- |
| 248 | + |
| 249 | +## 📊 Ejemplo de Output |
| 250 | + |
| 251 | +### PR Rechazado (con API key) |
| 252 | + |
| 253 | +``` |
| 254 | +❌ [ERROR] APIKeysDetector: Posible OpenAI API Key detectado |
| 255 | + - Patrón detectado: sk-ab****ijk (detectors/bad.py, línea 5) |
| 256 | + |
| 257 | +❌ [ERROR] PasswordsDetector: Password hardcodeado en 'DATABASE_PASSWORD' |
| 258 | + - Variable: DATABASE_PASSWORD (config.py, línea 12) |
| 259 | +
|
| 260 | +DECISIÓN: REJECT |
| 261 | +→ PR comentado y cerrado automáticamente |
| 262 | +``` |
| 263 | + |
| 264 | +### PR Aprobado (detector limpio) |
| 265 | + |
| 266 | +``` |
| 267 | +✅ [OK] DetectorFormatValidator: Estructura del detector válida |
| 268 | +✅ [OK] APIKeysDetector: Sin credenciales detectadas |
| 269 | +✅ [OK] PasswordsDetector: Sin passwords hardcodeados |
| 270 | +✅ [OK] SensitiveFilesDetector: Sin archivos sensibles |
| 271 | +
|
| 272 | +DECISIÓN: MERGE |
| 273 | +→ PR aprobado y mergeado automáticamente en 89ms |
| 274 | +``` |
| 275 | + |
| 276 | +Ver más ejemplos: [docs/example-outputs.md](docs/example-outputs.md) |
| 277 | + |
| 278 | +--- |
| 279 | + |
| 280 | +## 🔒 Modelo de Seguridad |
| 281 | + |
| 282 | +### Protección contra abuso |
| 283 | +- **Validación de paths**: Solo archivos en rutas explícitamente permitidas |
| 284 | +- **Análisis estático de AST**: Los detectores nuevos son analizados con `ast.parse()` antes de ser aceptados |
| 285 | +- **Imports prohibidos**: `subprocess`, `socket`, `requests`, `eval`, `exec` son bloqueados automáticamente |
| 286 | +- **Límites de tamaño**: PRs grandes requieren revisión manual |
| 287 | +- **Sin ejecución de código**: Los detectores NUNCA ejecutan el código que analizan, solo lo leen como texto |
| 288 | + |
| 289 | +### Qué requiere revisión manual |
| 290 | +Cualquier cambio en estas áreas **nunca se auto-mergea**: |
| 291 | +- El motor de decisión (`core/`, `scripts/`) |
| 292 | +- Los workflows de GitHub Actions |
| 293 | +- Las dependencias del proyecto |
0 commit comments