Как настроить проверку содержимого merge request (MR) в бесплатной версии GitLab (Community Edition)?

«Как настроить проверку содержимого merge request (MR) в бесплатной версии GitLab (Community Edition)?» — вопрос из категории Git, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В GitLab CE для автоматизации проверки содержимого MR я настраиваю комбинацию из CI/CD пайплайнов и server-side хуков. Вот как это делается.

1. Проверка через .gitlab-ci.yml (основной метод): В пайплайне можно добавить стадию validate, которая запускается для merge request и проверяет коммиты.

validate_mr:
  stage: validate
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Запуск только для MR
  script:
    # Пример: проверка, что сообщение коммита содержит JIRA-тикет
    - COMMIT_MSG=$(git log --oneline -n 1 $CI_COMMIT_SHA)
    - if ! echo "$COMMIT_MSG" | grep -qE "[A-Z]+-[0-9]+"; then
        echo "ERROR: Commit message must contain a task ID (e.g., PROJ-123). Found: $COMMIT_MSG"
        exit 1
      fi
    # Пример: проверка, что не изменяются критичные конфиги без тега
    - if git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA $CI_COMMIT_SHA | grep -q "production.yaml"; then
        if ! echo "$COMMIT_MSG" | grep -q "#production"; then
          echo "ERROR: Changing production.yaml requires '#production' tag in commit message."
          exit 1
        fi
      fi

Если скрипт завершится с ошибкой (exit 1), пайплайн упадет, и MR нельзя будет смержить, пока нарушения не исправлены.

2. Server-side hook (более строгий, но требует доступа к серверу): Хук update или pre-receive выполняется на сервере GitLab до принятия пуша. Это последний рубеж.

  • На сервере GitLab переходим в директорию репозитория: /var/opt/gitlab/git-data/repositories/<group>/<project>.git.
  • Создаем или редактируем хук в custom_hooks/:
    # /var/opt/gitlab/git-data/repositories/.../custom_hooks/pre-receive.d/01-check-commits
    #!/bin/bash
    while read oldrev newrev refname; do
      # Проверяем, это ли ветка MR (merge request создает refs/merge-requests/)
      if [[ $refname =~ refs/merge-requests/ ]]; then
        # Получаем список коммитов
        commits=$(git rev-list $oldrev..$newrev)
        for commit in $commits; do
          msg=$(git log --format=%B -n 1 $commit)
          # Проверка на наличие JIRA-тикета
          if ! [[ "$msg" =~ [A-Z]+-[0-9]+ ]]; then
            echo "[REJECTED] Commit $commit: message must contain a task ID (e.g., PROJ-456)."
            exit 1
          fi
        done
      fi
    done
  • Делаем файл исполняемым: chmod +x /path/to/hook.

3. Настройка Merge Request Approvals (ручная проверка): В настройках проекта (SettingsMerge requests) можно задать обязательное количество аппруверов, что гарантирует человеческий ревью перед мержем.