Руководство по интеграции с GitLab

Руководство по подключению CodeGraph к GitLab (self-managed или GitLab.com) для автоматизированного код-ревью, сканирования безопасности и инкрементального обновления CPG.

Содержание

Обзор

CodeGraph интегрируется с GitLab для автоматизированного код-ревью, сканирования безопасности и отслеживания технического долга. Три пути интеграции:

  • Конвейер CI/CD – CodeGraph как шаг в .gitlab-ci.yml
  • На основе вебхуков – события push/MR автоматически запускают инкрементальное обновление CPG и ревью
  • Автономный режим – развертывание рядом с GitLab, доступ через REST API / CLI / MCP

Полезная нагрузка вебхуков GitLab использует формат, специфичный для GitLab (object_attributes для MR, project для информации о репозитории). CodeGraph нормализует их в унифицированные модели, общие для всех 4 поддерживаемых платформ.

Предварительные требования

  • Экземпляр CodeGraph (Docker или автономный), доступный из раннеров GitLab CI
  • Проект GitLab с правами Maintainer или Owner (для настройки вебхуков)
  • Docker (для шагов конвейера CI)
  • Ключ API LLM: YANDEX_API_KEY, GIGACHAT_AUTH_KEY или OPENAI_API_KEY

Настройка вебхуков

Конечная точка: POST /api/v1/webhooks/gitlab (возвращает 202 Accepted)

Настройка в GitLab: Проект Settings > Webhooks > Add new webhook: 1. URL: https://<codegraph-host>/api/v1/webhooks/gitlab 2. Secret token: любая строка (простая верификация токена, не HMAC) 3. Trigger: отметьте Push events и Merge request events 4. SSL verification: включите, если CodeGraph использует валидный сертификат

Верификация токена

GitLab использует простую верификацию секретного токена (не HMAC-SHA256). CodeGraph сравнивает заголовок X-Gitlab-Token с настроенным секретом, используя сравнение с постоянным временем выполнения.

Коды ошибок: - 401 Unauthorized – отсутствует заголовок X-Gitlab-Token - 403 Forbidden – токен не совпадает с настроенным секретом

Примечание: В отличие от GitHub, который использует HMAC-SHA256 по телу запроса, GitLab отправляет секретный токен напрямую в заголовке X-Gitlab-Token. Это означает, что тело запроса не подписано и отсутствует заголовок timestamp для защиты от replay-атак. Для дополнительной безопасности используйте фильтрацию по IP-адресам или обратный прокси с mTLS.

Поддерживаемые события

Заголовок события (X-Gitlab-Event) Действие
Push Hook / push Инкрементальное обновление CPG через CPGUpdateQueue
Merge Request Hook / merge_request Запуск процесса код-ревью

События, не соответствующие этим типам, возвращаются с {"status": "skipped"}.

Конфигурация

Секция gitlab в config.yaml:

gitlab:
  webhook_secret: "your-gitlab-webhook-token"
  auto_update_on_push: true    # trigger incremental CPG update on push events
  api_url: "https://gitlab.com"   # or your self-managed instance URL

Определение типа события

CodeGraph определяет тип события из заголовка X-Gitlab-Event. Если заголовок отсутствует, используется резервное определение по структуре полезной нагрузки:

  • Присутствует ключ object_attributes или merge_request – событие merge_request
  • Присутствует ключ commits или (before + after) – событие push

Структура полезной нагрузки

Полезная нагрузка Push Hook (ключевые поля, используемые CodeGraph):

{
  "ref": "refs/heads/main",
  "before": "old_commit_sha",
  "after": "new_commit_sha",
  "project": {
    "git_http_url": "https://gitlab.com/org/repo.git",
    "path_with_namespace": "org/repo"
  },
  "user_name": "developer",
  "commits": [
    {
      "id": "new_commit_sha",
      "message": "feat: add feature",
      "author": {"name": "Developer"},
      "added": ["src/new.py"],
      "modified": ["src/existing.py"],
      "removed": []
    }
  ]
}

Полезная нагрузка Merge Request Hook (ключевые поля):

{
  "object_attributes": {
    "iid": 15,
    "action": "open",
    "source_branch": "feature-x",
    "target_branch": "main",
    "title": "Add feature X"
  },
  "user": {"username": "developer"},
  "project": {
    "git_http_url": "https://gitlab.com/org/repo.git",
    "path_with_namespace": "org/repo"
  }
}

Маппинг действий: openopened, updateupdated, closeclosed, mergemerged, reopenreopened.

Конвейер CI (.gitlab-ci.yml)

Базовый конвейер

Создайте .gitlab-ci.yml:

stages:
  - analyze
  - review
  - report

variables:
  PROJECT_LANGUAGE: python

cpg-update:
  stage: analyze
  image: ghcr.io/mkhlsavin/codegraph:latest
  script:
    - gocpg parse --input=. --output=/tmp/cpg.duckdb --lang=${PROJECT_LANGUAGE}
  artifacts:
    paths:
      - /tmp/cpg.duckdb
    expire_in: 1 hour
  only:
    - merge_requests
    - main

security-scan:
  stage: review
  image: ghcr.io/mkhlsavin/codegraph:latest
  needs: [cpg-update]
  script:
    - |
      DIFF=$(git diff ${CI_MERGE_REQUEST_DIFF_BASE_SHA}...HEAD)
      curl -sf -X POST "${CODEGRAPH_URL}/api/v1/security/scan-diff" \
        -H "Authorization: Bearer ${CODEGRAPH_TOKEN}" \
        -H "Content-Type: application/json" \
        -d "{\"diff_content\": $(echo "$DIFF" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))'), \"output_format\": \"sarif\"}" \
        -o gl-sast-report.json
  artifacts:
    reports:
      sast: gl-sast-report.json
  only:
    - merge_requests

mr-review:
  stage: review
  image: ghcr.io/mkhlsavin/codegraph:latest
  needs: [cpg-update]
  script:
    - |
      DIFF=$(git diff ${CI_MERGE_REQUEST_DIFF_BASE_SHA}...HEAD)
      curl -sf -X POST "${CODEGRAPH_URL}/api/v1/review/summary" \
        -H "Authorization: Bearer ${CODEGRAPH_TOKEN}" \
        -H "Content-Type: application/json" \
        -d "{\"diff_content\": $(echo "$DIFF" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))'), \"title\": \"${CI_MERGE_REQUEST_TITLE}\"}" \
        -o review-results.json
      cat review-results.json
  only:
    - merge_requests

report:
  stage: report
  image: ghcr.io/mkhlsavin/codegraph:latest
  needs: [security-scan, mr-review]
  script:
    - echo "Security scan and review completed"
    - "[ -f gl-sast-report.json ] && cat gl-sast-report.json | python3 -c \"import sys,json; r=json.load(sys.stdin); print(f'Findings: {r.get(\\\"total_count\\\", 0)}')\""
  only:
    - merge_requests

Обязательные переменные CI/CD

Настройте в Settings > CI/CD > Variables:

Имя Тип Описание
CODEGRAPH_URL Variable Конечная точка API CodeGraph (напр. https://codegraph.example.com)
CODEGRAPH_TOKEN Secret (masked) Токен аутентификации API CodeGraph
PROJECT_LANGUAGE Variable Язык исходного кода (по умолчанию: python)

Интеграция с SAST

Вывод CodeGraph в формате SARIF интегрируется с панелью безопасности GitLab Security Dashboard. Используйте ключ artifacts:reports:sast для загрузки результатов:

artifacts:
  reports:
    sast: gl-sast-report.json

Результаты отображаются в Security & Compliance > Vulnerability Report (GitLab Ultimate) или в виджете мерж-реквеста (для SAST доступно на всех тарифах).

Конечные точки REST API

POST /api/v1/webhooks/gitlab – Приемник вебхуков

См. Настройка вебхуков.

POST /api/v1/security/scan-diff – Сканирование безопасности

Сканирует необработанный унифицированный diff на наличие уязвимостей безопасности.

Запрос (ScanDiffRequest):

{
  "diff_content": "unified diff string",
  "output_format": "sarif"
}
Поле Тип По умолчанию Описание
diff_content string Необработанный унифицированный diff (обязательное)
output_format string "json" "json" или "sarif"

Ответ (ScanDiffResponse):

{
  "findings": [
    {
      "finding_id": "f-001",
      "pattern_id": "CWE-89",
      "pattern_name": "SQL Injection",
      "category": "security",
      "severity": "high",
      "method_name": "execute_query",
      "filename": "src/db.py",
      "line_number": 42,
      "description": "User input concatenated into SQL query",
      "cwe_ids": ["CWE-89"],
      "confidence": 0.92
    }
  ],
  "new_count": 1,
  "fixed_count": 0,
  "total_count": 1,
  "critical_count": 0,
  "high_count": 1,
  "medium_count": 0,
  "sarif": {},
  "low_count": 0
}

POST /api/v1/review/summary – Резюме мерж-реквеста

Генерирует структурированное резюме из любого унифицированного diff (независимо от платформы).

{
  "diff_content": "unified diff string",
  "title": "Optional MR title",
  "description": "Optional MR description"
}

Ответ: summary, changed_files, additions, deletions, changed_methods, risk_areas.

POST /api/v1/review/commit-message – Сообщение коммита

Генерирует сообщение коммита в формате conventional commits из diff.

{
  "diff_content": "unified diff string"
}

Ответ: message, type, scope, files_changed.

POST /api/v1/review/mr – Ревью мерж-реквеста GitLab

Рецензирование мерж-реквеста GitLab напрямую — diff загружается из GitLab API (не нужно передавать raw diff).

{
  "project_id": "org/repo",
  "mr_iid": 15,
  "gitlab_url": "https://gitlab.com",
  "task_description": "Optional review focus",
  "dod_items": ["No security issues", "Tests pass"]
}

Ответ: recommendation, score, findings[], dod_validation[], summary, processing_time_ms, request_id.

GET /api/v1/webhooks/status/{project_id} – Статус обновления

Возвращает последний статус конвейера обновления CPG для проекта.

{
  "project_id": "org/repo",
  "last_update": "2026-03-09T12:00:00+00:00",
  "status": "completed",
  "commit_sha": "ddd444",
  "duration_ms": 2345,
  "gocpg_status": "completed",
  "chromadb_synced": 3,
  "error": null
}
Поле Тип Описание
status string completed, failed, in_progress или unknown
last_update string Метка времени последнего завершенного обновления в формате ISO 8601
duration_ms int Время выполнения конвейера в миллисекундах
gocpg_status string Статус инкрементального обновления GoCPG
chromadb_synced int Количество обновленных коллекций ChromaDB

Инструменты MCP

Когда CodeGraph работает как MCP-сервер (python -m src.mcp), AI-агенты могут использовать инструменты, учитывающие CPG:

Инструмент Описание
codegraph_project_context Обзор проекта: статистика CPG, языки, горячие точки, результаты безопасности
codegraph_file_context Информация о файле: методы, метрики, вызывающие, вызываемые, мертвый код, безопасность
codegraph_diff_context Анализ области влияния для измененных файлов
codegraph_query Выполнение SQL-запросов к CPG DuckDB
codegraph_find_callers Поиск всех вызывающих функцию
codegraph_find_callees Поиск всех функций, вызываемых данной функцией
codegraph_taint_analysis Отслеживание потоков данных от источников к стокам

Эти инструменты доступны, когда CodeGraph работает как MCP-сервер (python -m src.mcp).

Инкрементальное обновление CPG

При получении события push через вебхук CodeGraph запускает полный конвейер инкрементального обновления:

  1. Определение проекта – сопоставление по project_id, URL репозитория (git_http_url) или активному проекту
  2. Обновление GoCPG – инкрементальное обновление CPG через gRPC/subprocess (from_committo_commit)
  3. Синхронизация ChromaDB – обновление коллекций векторного хранилища для измененных файлов
  4. Уведомление по WebSocket – широковещательная рассылка события cpg.update.complete подключенным клиентам

Поведение конвейера: - Дублирующиеся события push (тот же проект + SHA коммита) дедуплицируются - Быстрые последовательные push в один проект объединяются (слияние измененных файлов, последний коммит) - При сбое GoCPG автоматически выполняется повторная попытка через 60 секунд - Синхронизация ChromaDB продолжается даже при сбое обновления GoCPG - Вебхук всегда немедленно возвращает 202 Accepted (обработка выполняется асинхронно)

Мониторинг статуса конвейера через GET /api/v1/webhooks/status/{project_id}.

Настройка Docker-образа

Образы публикуются в GHCR через .github/workflows/publish-ghcr.yml, тегируются по тегам версий (v*) и latest.

docker pull ghcr.io/mkhlsavin/codegraph:latest
docker run --rm ghcr.io/mkhlsavin/codegraph:latest python -m src.cli health

Включает бинарный файл GoCPG и поддерживает 11 языков (C, C++, C#, Go, Java, JavaScript, Kotlin, PHP, Python, Ruby, TypeScript).

Для self-managed GitLab с приватным реестром контейнеров:

docker tag ghcr.io/mkhlsavin/codegraph:latest registry.company.com/codegraph:latest
docker push registry.company.com/codegraph:latest

Затем укажите registry.company.com/codegraph:latest в .gitlab-ci.yml.

Устранение неполадок

Ошибка токена вебхука (401/403)

401 Unauthorized – заголовок X-Gitlab-Token отсутствует: - Убедитесь, что секретный токен настроен в параметрах вебхука GitLab - Проверьте правильность URL вебхука (/api/v1/webhooks/gitlab, а не /api/v1/webhooks/github)

403 Forbidden – токен не совпадает: - Убедитесь, что токен в GitLab совпадает с config.yaml > gitlab.webhook_secret - Токены сравниваются с постоянным временем выполнения; проверьте наличие завершающих пробелов или переводов строк

Вебхук возвращает 400

  • Проверьте, что полезная нагрузка является корректным JSON
  • Убедитесь, что Content-Type установлен в application/json (GitLab устанавливает это по умолчанию)

Конвейер CI не может подключиться к CodeGraph

  • CODEGRAPH_URL должен быть доступен из раннеров GitLab CI
  • Проверка: curl -sf ${CODEGRAPH_URL}/api/v1/health
  • Для self-managed GitLab: проверьте сетевые правила между раннером и CodeGraph
  • Для общих раннеров (GitLab.com): CodeGraph должен быть публично доступен или использовать туннель

Отчет SAST не отображается

  • Проверьте, что путь артефакта совпадает: artifacts:reports:sast: gl-sast-report.json
  • Используйте output_format: "sarif" в запросе scan-diff
  • Отчеты SAST требуют, чтобы мерж-реквест был открыт (не объединен)

Ревью мерж-реквеста возвращает пустые результаты

  • Убедитесь, что CI_MERGE_REQUEST_DIFF_BASE_SHA доступна (требуется триггер merge_requests)
  • Проверьте, что установлен GIT_DEPTH: "0" в variables: для полной истории git (эквивалент fetch-depth: 0 в GitLab CI)
  • Проверьте токен API: curl -sf ${CODEGRAPH_URL}/api/v1/health -H "Authorization: Bearer ${CODEGRAPH_TOKEN}"

Проблемы с сертификатами self-managed GitLab

Если CodeGraph не может подключиться к self-managed экземпляру GitLab с самоподписанным сертификатом: - Смонтируйте сертификат удостоверяющего центра в контейнер CodeGraph - Установите переменную окружения SSL_CERT_FILE, указывающую на файл сертификата удостоверяющего центра

Инкрементальное обновление показывает “unavailable”

  • Убедитесь, что GoCPG установлен и доступен: gocpg --version
  • Проверьте, что переменная окружения GOCPG_PATH указывает на бинарный файл GoCPG
  • Просмотрите журналы: grep "GoCPG" /var/log/codegraph/*.log

Дальнейшие шаги