Hybrydowe wyszukiwanie w repozytoriach GitLab: API i głębokie skanowanie konfiguracji
Wraz ze wzrostem liczby projektów w GitLab wyszukiwanie konkretnych linii w kodzie, plikach YAML, JSON i .env staje się problemem. Standardowe wyszukiwanie w interfejsie użytkownika i API działa szybko w kodzie, ale pomija konfiguracje. Rozwiązaniem jest hybrydowy skrypt w Pythonie z python-gitlab: API Search dla kodu i rekurencyjne przeszukiwanie dla konfiguracji. Czas wyszukiwania w ponad 100 projektach skrócił się do minut.
Analiza alternatywnych podejść
Przed opracowaniem oceniliśmy istniejące metody. Żadna nie pokrywała zadania w pełni bez kompromisów.
| Podejście | Zalety | Wady |
|--------|-------|--------|
| GitLab UI | Szybkie uruchomienie | Ręczne dla 100+ projektów, słabe w konfiguracjach |
| Lokalne grep/ripgrep | Pełna kontrola | Klonowanie wszystkich repozytoriów zajmuje godziny |
| GitLab API Search | Dostępny zdalnie | Pomija YAML/JSON/env |
| Sourcegraph | Potężny indeks | Wymaga wdrożenia infrastruktury |
Hybrydowy skrypt okazał się optymalny: wykorzystuje mocne strony API i dodaje przeszukiwanie dla słabych punktów bez zewnętrznych zależności.
Różnice w wyszukiwaniu według typów plików
GitLab indeksuje kod i dokumentację niezawodnie, ale konfiguracje często pozostają poza wyszukiwaniem.
- Kod (.py, .js, .go, .ts): API Search — indeksacja pokrywa w pełni.
- Dokumentacja (.md, .txt): API Search — wystarczająca szybkość i dokładność.
- Konfiguracje (.yml, .yaml, .json, .env): Deep Search — rekurencyjne tree + pobieranie zawartości.
- Pliki binarne: Wykluczone dla oszczędności zasobów.
Logika: delegować zadanie narzędziu dla mocnych typów, ręcznie uzupełniać słabe.
Architektura skryptu
Skrypt działa w potoku:
- Pobranie listy projektów grupy z podgrupami.
- Filtracja archiwalnych i nieaktywnych.
- Równoległa obróbka: API Search + Deep Search.
- Agregacja wyników.
- Generowanie raportów.
Grupa GitLab → projects.list() → filter active
↓
Równolegle: API Search (code) + Deep Search (configs)
↓
Merge → Szczegółowy raport + Podsumowanie + Błędy
Wyszukiwanie ograniczone do gałęzi master dla aktualnych konfiguracji. Rozszerzenie na wszystkie gałęzie jest możliwe, ale zwiększa czas.
Implementacja kluczowych komponentów
Pobieranie projektów
group = gl.groups.get(GROUP_ID)
all_projects = group.projects.list(include_subgroups=True, all=True)
Filtrują według statusu archived=false i last_activity.
API Search dla kodu
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
Przetwarza bloby według rozszerzeń kodu.
Deep Search dla konfiguracji
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
Rekurencyjne tree, pobieranie zawartości, wyszukiwanie tekstowe.
Równoległa obróbka
ThreadPoolExecutor z 3 wątkami przyspiesza dla 100+ projektów:
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)
Skraca czas z godzin do minut bez problemów GIL w zadaniu IO-bound.
Formaty raportów
Szczegółowy: Projekt, ścieżka, termin, linia, metoda wyszukiwania.
Przykład:
PROJEKT: service-a
Ścieżka: backend/service-a
'SERVICE_EXAMPLE': 2 wystąpienia
- deploy/prod/values.yml:42 [Deep]
Linia 42: SERVICE_EXAMPLE: "{{ .Values.secrets.apiKey }}"
Podsumowujący: Liczba projektów, wystąpień, API vs Deep.
Czynniki przyspieszenia
- Wykluczenie niepotrzebnych plików/projektów.
- API dla 80% przypadków (kod).
- Równoległość.
- Skupienie na master.
Ograniczenia
- Tylko master.
- Brak regex.
- Brak deduplikacji.
- Wyjście konsolowe.
Co jest ważne
- Hybryd minimalizuje słabości GitLab Search w konfiguracjach.
- Równoległość z 3 wątkami optymalna dla limitów API.
- Filtracja projektów zmniejsza obciążenie o 30–50%.
- Deep Search dokładny dla YAML/JSON/env.
- Nadaje się do jednorazowych sprawdzeń bez infrastruktury.
— Editorial Team
Brak komentarzy.