Búsqueda Híbrida en Repositorios de GitLab: API y Escaneo Profundo de Configuraciones
A medida que crece el número de proyectos en GitLab, buscar cadenas específicas en código, archivos YAML, JSON y .env se convierte en un desafío. La búsqueda estándar de la interfaz y la API funciona rápidamente para código, pero omite configuraciones. La solución es un script híbrido en Python que usa python-gitlab: Búsqueda por API para código y recorrido recursivo para configuraciones. El tiempo de búsqueda en más de 100 proyectos se redujo a minutos.
Análisis de Enfoques Alternativos
Antes del desarrollo, evaluamos métodos existentes. Ninguno cubría completamente la tarea sin compromisos.
| Enfoque | Ventajas | Desventajas |
|--------|-------|--------|
| Interfaz de GitLab | Rápido de iniciar | Manual para 100+ proyectos, débil en configuraciones |
| grep/ripgrep local | Control total | Clonar todos los repositorios toma horas |
| Búsqueda por API de GitLab | Disponible de forma remota | Omite YAML/JSON/env |
| Sourcegraph | Indexación potente | Requiere despliegue de infraestructura |
El rastreador híbrido demostró ser óptimo: aprovecha las fortalezas de la API y añade recorrido para puntos débiles sin dependencias externas.
Diferencias en la Búsqueda por Tipos de Archivo
GitLab indexa de forma confiable código y documentación, pero las configuraciones a menudo quedan fuera de la búsqueda.
- Código (.py, .js, .go, .ts): Búsqueda por API — la indexación cubre completamente.
- Documentación (.md, .txt): Búsqueda por API — velocidad y precisión suficientes.
- Configuraciones (.yml, .yaml, .json, .env): Búsqueda Profunda — árbol recursivo + obtención de contenido.
- Archivos binarios: Excluidos para ahorrar recursos.
Lógica: delegar tareas a la herramienta para tipos fuertes, manejar manualmente los débiles.
Arquitectura del Script
El script sigue una canalización:
- Obtener lista de proyectos en un grupo con subgrupos.
- Filtrar los archivados e inactivos.
- Procesamiento paralelo: Búsqueda por API + Búsqueda Profunda.
- Agregar resultados.
- Generar informes.
Grupo de GitLab → projects.list() → filtrar activos
↓
Paralelo: Búsqueda por API (código) + Búsqueda Profunda (configuraciones)
↓
Fusionar → Informe detallado + Resumen + Errores
La búsqueda se limita a la rama master para configuraciones actuales. Extender a todas las ramas es posible pero aumenta el tiempo.
Implementación de Componentes Clave
Obtención de Proyectos
group = gl.groups.get(GROUP_ID)
all_projects = group.projects.list(include_subgroups=True, all=True)
Filtrar por estado archived=false y last_activity.
Búsqueda por API para Código
def api_search(gl, project_id, search_terms):
results = {term: [] for term in search_terms}
for term in search_terms:
blobs = gl.search('blobs', term, project_id=project_id)
for blob in blobs:
file_path = blob.get('path', '')
file_ext = os.path.splitext(file_path)[1].lower()
if file_ext in CODE_EXTENSIONS or file_ext == '':
results[term].append({
'path': file_path,
'url': blob.get('web_url', '#'),
'found_by': 'API'
})
return results
Procesa blobs por extensiones de código.
Búsqueda Profunda para Configuraciones
def deep_search_configs(gl, project_id, search_terms):
results = {term: [] for term in search_terms}
project = gl.projects.get(project_id)
files = project.repository_tree(recursive=True, ref='master')
for file in files:
if file['type'] != 'blob':
continue
ext = os.path.splitext(file['name'])[1].lower()
if ext not in CONFIG_EXTENSIONS:
continue
content = project.files.get(file_path=file['path'], ref='master').decode()
content_lower = content.lower()
for term in search_terms:
if term.lower() in content_lower:
results[term].append({
'path': file['path'],
'found_by': 'Deep'
})
return results
Árbol recursivo, obtener contenido, búsqueda de cadenas.
Paralelización del Procesamiento
ThreadPoolExecutor con 3 trabajadores acelera para 100+ proyectos:
with ThreadPoolExecutor(max_workers=3) as executor:
futures = {executor.submit(process_one_project, gl, p): p for p in active_projects}
for future in as_completed(futures):
result = future.result()
results_list.append(result)
Reduce el tiempo de horas a minutos sin problemas de GIL en tareas vinculadas a E/S.
Formatos de Informe
Detallado: Proyecto, ruta, término, línea, método de búsqueda.
Ejemplo:
PROYECTO: service-a
Ruta: backend/service-a
'SERVICE_EXAMPLE': 2 ocurrencias
- deploy/prod/values.yml:42 [Profundo]
Línea 42: SERVICE_EXAMPLE: "{{ .Values.secrets.apiKey }}"
Resumen: Número de proyectos, ocurrencias, API vs Profundo.
Factores de Velocidad
- Excluir archivos/proyectos innecesarios.
- API para el 80% de los casos (código).
- Paralelismo.
- Enfoque en master.
Limitaciones
- Solo master.
- Sin expresiones regulares.
- Sin deduplicación.
- Salida por consola.
Puntos Clave
- El enfoque híbrido minimiza las debilidades de la Búsqueda de GitLab para configuraciones.
- Paralelismo con 3 hilos es óptimo para límites de tasa de la API.
- Filtrar proyectos reduce la carga en un 30–50%.
- La Búsqueda Profunda es precisa para YAML/JSON/env.
- Adecuado para verificaciones puntuales sin infraestructura.
— Editorial Team
Aún no hay comentarios.