Powrót do strony głównej

Hybrydowe wyszukiwanie kodu w GitLab w 100+ projektach

Hybrydowy skrypt przyspiesza wyszukiwanie ciągów w 100+ projektach GitLab: API Search dla kodu i dokumentacji, rekurencyjne przeszukiwanie dla konfiguracji. Równoległe przetwarzanie z ThreadPoolExecutor. Szczegółowy kod i raporty dla technicznych audytów.

Szybkie wyszukiwanie w 100+ repozytoriach GitLab: hybrydowy API+Deep
Advertisement 728x90

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 |

Google AdInline article slot

|--------|-------|--------|

| 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 |

Google AdInline article slot

| 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.

Google AdInline article slot

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

Advertisement 728x90

Czytaj dalej