Recherche hybride de dépôts GitLab : API et analyse approfondie des configurations
À mesure que le nombre de projets dans GitLab augmente, rechercher des chaînes spécifiques dans le code, les fichiers YAML, JSON et .env devient un défi. La recherche standard via l'interface utilisateur et l'API est rapide pour le code mais ignore les configurations. La solution est un script Python hybride utilisant python-gitlab : recherche API pour le code et parcours récursif pour les configurations. Le temps de recherche sur plus de 100 projets a été réduit à quelques minutes.
Analyse des approches alternatives
Avant le développement, nous avons évalué les méthodes existantes. Aucune ne couvrait entièrement la tâche sans compromis.
| Approche | Avantages | Inconvénients |
|--------|-------|--------|
| Interface GitLab | Démarrage rapide | Manuel pour 100+ projets, faible sur les configurations |
| grep/ripgrep local | Contrôle total | Le clonage de tous les dépôts prend des heures |
| Recherche API GitLab | Disponible à distance | Ignore YAML/JSON/env |
| Sourcegraph | Indexation puissante | Nécessite un déploiement d'infrastructure |
Le crawler hybride s'est avéré optimal : il exploite les forces de l'API et ajoute un parcours pour les points faibles sans dépendances externes.
Différences de recherche par types de fichiers
GitLab indexe de manière fiable le code et la documentation, mais les configurations restent souvent en dehors de la recherche.
- Code (.py, .js, .go, .ts): Recherche API — l'indexation couvre entièrement.
- Documentation (.md, .txt): Recherche API — vitesse et précision suffisantes.
- Configurations (.yml, .yaml, .json, .env): Recherche approfondie — arborescence récursive + récupération du contenu.
- Fichiers binaires: Exclus pour économiser des ressources.
Logique : déléguer les tâches à l'outil pour les types forts, traiter manuellement les faibles.
Architecture du script
Le script suit un pipeline :
- Obtenir la liste des projets dans un groupe avec sous-groupes.
- Filtrer les projets archivés et inactifs.
- Traitement parallèle : Recherche API + Recherche approfondie.
- Agréger les résultats.
- Générer des rapports.
Groupe GitLab → projects.list() → filtrer actifs
↓
Parallèle : Recherche API (code) + Recherche approfondie (configurations)
↓
Fusion → Rapport détaillé + Résumé + Erreurs
La recherche est limitée à la branche master pour les configurations actuelles. L'extension à toutes les branches est possible mais augmente le temps.
Implémentation des composants clés
Obtention des projets
group = gl.groups.get(GROUP_ID)
all_projects = group.projects.list(include_subgroups=True, all=True)
Filtrer par statut archived=false et last_activity.
Recherche API pour le code
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
Traite les blobs par extensions de code.
Recherche approfondie pour les configurations
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
Arborescence récursive, récupération du contenu, recherche de chaînes.
Parallélisation du traitement
ThreadPoolExecutor avec 3 travailleurs accélère pour 100+ projets :
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)
Réduit le temps de plusieurs heures à quelques minutes sans problèmes de GIL dans les tâches liées aux E/S.
Formats de rapport
Détaillé : Projet, chemin, terme, ligne, méthode de recherche.
Exemple :
PROJET : service-a
Chemin : backend/service-a
'SERVICE_EXAMPLE' : 2 occurrences
- deploy/prod/values.yml:42 [Deep]
Ligne 42 : SERVICE_EXAMPLE: "{{ .Values.secrets.apiKey }}"
Résumé : Nombre de projets, occurrences, API vs Deep.
Facteurs de vitesse
- Exclusion des fichiers/projets inutiles.
- API pour 80 % des cas (code).
- Parallélisme.
- Concentration sur master.
Limitations
- Master uniquement.
- Pas d'expressions régulières.
- Pas de déduplication.
- Sortie console.
Points clés
- L'approche hybride minimise les faiblesses de la recherche GitLab pour les configurations.
- Le parallélisme avec 3 threads est optimal pour les limites de débit de l'API.
- Le filtrage des projets réduit la charge de 30 à 50 %.
- La recherche approfondie est précise pour YAML/JSON/env.
- Adapté aux vérifications ponctuelles sans infrastructure.
— Editorial Team
Aucun commentaire pour le moment.