Как проверять merge-реквизиты в бесплатной версии GitLab
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Отличный вопрос, который затрагивает один из ключевых аспектов поддержания чистоты и управляемости кодовой базы в CI/CD. В бесплатной версии GitLab (раньше Core, теперь Free) нет встроенной, готовой к использованию функции Merge Request Approvals в её расширенном виде (правила, обязательные апруверы, контроль по числу апрувов). Однако есть мощный и гибкий механизм, который полностью позволяет решать эту задачу — GitLab CI/CD в связке с Merge Request Pipelines и проверками через .gitlab-ci.yml.
Основная идея: мы создаем CI/CD пайплайн, который запускается для каждого Merge Request (MR). Этот пайплайн выполняет скрипты (на bash, Python и т.д.), которые анализируют содержимое MR и "ломаются" (возвращают ненулевой код выхода), если условия не выполнены. Сломанный пайплайн блокирует возможность слияния (merge), пока ошибки не будут исправлены.
Вот основные подходы и примеры реализации.
1. Проверка через CI/CD Job с использованием Bash и Git
Создаем джобу в .gitlab-ci.yml, которая будет запускаться только для MR. Она использует команды git diff для анализа изменений.
stages:
- validation
check_commit_messages:
stage: validation
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" # Ключевое правило: только для MR
script:
# Получаем список коммитов в MR (от целевой ветки до последнего коммита MR)
- |
# Проверка формата сообщений коммитов (например, Convential Commits)
for commit in $(git log --oneline --no-merges $CI_MERGE_REQUEST_TARGET_BRANCH_NAME..$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME | awk '{print $1}'); do
commit_msg=$(git log --format=%B -n 1 $commit)
if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore)\(?(\w+)?\)?:\s.+"; then
echo "❌ Коммит $commit имеет неверный формат сообщения: '$commit_msg'"
echo " Ожидается формат: type(scope): description (например, feat(auth): add login button)"
exit 1
fi
done
echo "✅ Все сообщения коммитов соответствуют формату."
2. Проверка наличия ссылки на задачу (Issue) или Jira-тикета
Часто требуется, чтобы в описании MR или в названии ветки была ссылка на задачу из трекера.
check_mr_description:
stage: validation
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
# Проверяем, что в описании MR есть ссылка на Issue (например, #123 или JIRA-123)
- |
if ! echo "$CI_MERGE_REQUEST_DESCRIPTION" | grep -qE "((#|!)\d+|([A-Z]+-\d+))"; then
echo "❌ В описании Merge Request отсутствует ссылка на Issue или тикет (например, #123 или PROJECT-456)."
echo " Описание MR: $CI_MERGE_REQUEST_DESCRIPTION"
exit 1
fi
echo "✅ Ссылка на задачу найдена в описании MR."
3. Проверка изменений в критических файлах (например, миграций БД)
Можно требовать дополнительных проверок, если затронуты определенные файлы.
check_database_migrations:
stage: validation
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes: # Запускаем джобу только если изменились файлы в db/migrate/
- db/migrate/*.rb
script:
- |
# Пример: проверяем, что к миграции приложен SQL-скрипт отката (rollback)
for file in $(git diff --name-only $CI_MERGE_REQUEST_TARGET_BRANCH_NAME..$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME -- db/migrate/); do
if [[ ! -f "${file%.rb}_rollback.sql" ]]; then
echo "❌ Для миграции $file не найден файл отката (${file%.rb}_rollback.sql)."
exit 1
fi
done
echo "✅ Для всех миграций есть скрипты отката."
4. Использование внешних инструментов и скриптов
Для сложных проверок можно использовать отдельные скрипты на Python, Node.js и т.д.
validate_mr_with_python:
stage: validation
image: python:3.11-slim # Используем специфичный образ
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
before_script:
- pip install requests # Устанавливаем зависимости, если нужны
script:
- python .gitlab/scripts/validate_mr.py # Выносим логику в отдельный файл
А содержимое .gitlab/scripts/validate_mr.py может быть таким:
#!/usr/bin/env python3
import os
import sys
import re
mr_description = os.environ.get('CI_MERGE_REQUEST_DESCRIPTION', '')
target_branch = os.environ.get('CI_MERGE_REQUEST_TARGET_BRANCH_NAME', '')
# Пример: проверка, что в main/master нельзя мержить без тега [PROD-READY]
if target_branch in ['main', 'master']:
if '[PROD-READY]' not in mr_description:
print("[ERROR] Мерж в main/master требует тега [PROD-READY] в описании MR.")
sys.exit(1)
print("Все проверки пройдены.")
sys.exit(0)
5. Комплексный пример: требуем label и апрув от определенного пользователя (эмулируем Approvals)
Так как в Free нет обязательных апруверов, мы можем эмулировать это через проверку labels и упоминаний в комментариях.
check_approval_emulation:
stage: validation
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
# Используем GitLab API для проверки лейблов и комментариев
# Требуем наличие лейбла 'tech-lead-review'
- |
MR_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}"
MR_DATA=$(curl --silent --header "PRIVATE-TOKEN: $GITLAB_CI_TOKEN" "$MR_URL")
LABELS=$(echo "$MR_DATA" | jq -r '.labels[]')
if ! echo "$LABELS" | grep -q "tech-lead-review"; then
echo "❌ MR должен иметь лейбл 'tech-lead-review'."
exit 1
fi
# Проверяем, что есть комментарий от определенного пользователя с :+1:
NOTES_URL="${MR_URL}/notes"
NOTES_DATA=$(curl --silent --header "PRIVATE-TOKEN: $GITLAB_CI_TOKEN" "$NOTES_URL")
if ! echo "$NOTES_DATA" | jq -r '.[] | select(.author.username == "senior_dev") | .body' | grep -q ":\+1:"; then
echo "❌ Не найден апрув (комментарий с :+1:) от пользователя senior_dev."
exit 1
fi
echo "✅ Все условия эмулированного апрува выполнены."
Важные моменты и лучшие практики:
- Токен доступа: Для работы с GitLab API в скриптах нужно создать Project Access Token или использовать
CI_JOB_TOKEN(но у него могут быть ограничения на чтение). Безопаснее хранить его в CI/CD Variables (Settings > CI/CD > Variables) какGITLAB_CI_TOKENс маской. - Переменные GitLab CI: Используйте богатый набор предопределенных переменных, таких как
CI_MERGE_REQUEST_*,CI_COMMIT_*,CI_PROJECT_*— они невероятно полезны. - Правила (rules): Тщательно настраивайте
rulesдля джоб, используяchanges,if,variablesчтобы пайплайны были эффективными и запускались только когда нужно. - Визуальная проверка: Размещайте такие валидационные джобы в начале пайплайна (например, в stage
validation). Их failure будет четко виден в интерфейсе MR и заблокирует кнопку merge.
Заключение:
Несмотря на отсутствие графического интерфейса для правил апрува, бесплатная версия GitLab предоставляет через CI/CD более мощный и программируемый инструмент для проверки merge-реквизитов. Вы можете создать любые, даже самые сложные правила, адаптированные под процессы вашей команды. Главное — правильно структурировать .gitlab-ci.yml и использовать возможности GitLab API для анализа MR. Это требует некоторой настройки, но в результате дает полный контроль над качеством вливаемого кода.