하이브리드 GitLab 저장소 검색: API와 깊은 설정 스캔
GitLab의 프로젝트 수가 증가함에 따라 코드, YAML, JSON, .env 파일에서 특정 문자열을 검색하는 것은 어려운 과제가 됩니다. 표준 UI 및 API 검색은 코드에 대해서는 빠르게 작동하지만 설정 파일을 놓칩니다. 해결책은 python-gitlab을 사용한 하이브리드 Python 스크립트입니다: 코드는 API 검색을, 설정 파일은 재귀적 순회를 사용합니다. 100개 이상의 프로젝트에서 검색 시간이 몇 분으로 단축되었습니다.
대안적 접근법 분석
개발 전에 기존 방법들을 평가했습니다. 어떤 방법도 타협 없이 작업을 완전히 커버하지 못했습니다.
| 접근법 | 장점 | 단점 |
|--------|-------|--------|
| GitLab UI | 빠른 시작 | 100개 이상 프로젝트에 수동, 설정 파일 검색 약함 |
| 로컬 grep/ripgrep | 완전한 제어 | 모든 저장소 클론에 수 시간 소요 |
| GitLab API 검색 | 원격으로 사용 가능 | YAML/JSON/env 파일 누락 |
| Sourcegraph | 강력한 인덱싱 | 인프라 배포 필요 |
하이브리드 크롤러가 최적임이 입증되었습니다: API의 강점을 활용하고 외부 의존성 없이 약점을 순회로 보완합니다.
파일 유형별 검색 차이
GitLab은 코드와 문서를 안정적으로 인덱싱하지만, 설정 파일은 종종 검색 범위 밖에 남습니다.
- 코드 (.py, .js, .go, .ts): API 검색 — 인덱싱이 완전히 커버합니다.
- 문서 (.md, .txt): API 검색 — 충분한 속도와 정확도.
- 설정 파일 (.yml, .yaml, .json, .env): 깊은 검색 — 재귀적 트리 + 내용 가져오기.
- 바이너리 파일: 자원 절약을 위해 제외.
논리: 강한 유형은 도구에 위임, 약한 유형은 수동 처리.
스크립트 아키텍처
스크립트는 파이프라인을 따릅니다:
- 하위 그룹을 포함한 그룹 내 프로젝트 목록 가져오기.
- 보관 및 비활성 프로젝트 필터링.
- 병렬 처리: API 검색 + 깊은 검색.
- 결과 집계.
- 보고서 생성.
GitLab 그룹 → projects.list() → 활성 필터링
↓
병렬: API 검색 (코드) + 깊은 검색 (설정 파일)
↓
병합 → 상세 보고서 + 요약 + 오류
검색은 현재 설정을 위해 master 브랜치로 제한됩니다. 모든 브랜치로 확장 가능하지만 시간이 증가합니다.
주요 구성 요소 구현
프로젝트 가져오기
group = gl.groups.get(GROUP_ID)
all_projects = group.projects.list(include_subgroups=True, all=True)
상태 archived=false 및 last_activity로 필터링.
코드 API 검색
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
코드 확장자로 blob 처리.
설정 파일 깊은 검색
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
재귀적 트리, 내용 가져오기, 문자열 검색.
처리 병렬화
3명의 작업자로 ThreadPoolExecutor를 사용하여 100개 이상 프로젝트 속도 향상:
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)
IO 바운드 작업에서 GIL 문제 없이 시간을 수 시간에서 몇 분으로 단축.
보고서 형식
상세: 프로젝트, 경로, 용어, 줄, 검색 방법.
예시:
PROJECT: service-a
Path: backend/service-a
'SERVICE_EXAMPLE': 2회 발생
- deploy/prod/values.yml:42 [Deep]
Line 42: SERVICE_EXAMPLE: "{{ .Values.secrets.apiKey }}"
요약: 프로젝트 수, 발생 횟수, API 대 깊은 검색.
속도 요소
- 불필요한 파일/프젝트 제외.
- 80% 경우에 API 사용 (코드).
- 병렬화.
- master에 집중.
제한 사항
- master만.
- 정규식 없음.
- 중복 제거 없음.
- 콘솔 출력.
핵심 포인트
- 하이브리드 방식은 GitLab 검색의 설정 파일 약점을 최소화합니다.
- 3개의 스레드로 병렬화는 API 속도 제한에 최적입니다.
- 프로젝트 필터링으로 부하 30–50% 감소.
- 깊은 검색은 YAML/JSON/env에 정확합니다.
- 인프라 없이 일회성 검사에 적합.
— Editorial Team
아직 댓글이 없습니다.