Skip to content

GitLab Post-Receive Hook: Auto MR + YouTrack Integration

Summary

Server-side post-receive hook для GitLab, который при пуше ветки автоматически создаёт Merge Request и линкует его с задачей в YouTrack.

Decisions

ВопросРешение
Паттерн task ID[A-Z]+-\d+ — первое вхождение в любом месте имени ветки
Конвенция ветокЛюбой формат: DEV-123-desc, feature/DEV-123-desc, fix/DEP-45
Target branchhotfix/*main, всё остальное → develop
Валидация задачиYouTrack API — MR создаётся только если задача существует
Если задача не найденаWarning в git push output, пуш проходит
Статусы в YouTrackНе менять — хук только создаёт MR
Title MR{TASK_ID}: {summary из YouTrack}
ДедупликацияПроверка existing opened MR по source_branch через GitLab API
Несколько task ID в веткеБерём первый найденный
Управление хукомОтдельный репозиторий partizap-hooks (версионирование, review)
МасштабированиеПока один проект (partizap-frontend), расширяемо на мульти-репо

Architecture

Инфраструктура

Всё на VPS2 (2a03:6f00:a::1:c28f, доступ через VPS1 85.239.48.136, ключ partizap_main).

Репозиторий partizap-hooks

partizap-hooks/
├── hooks/
│   └── post-receive              # Основной скрипт хука (bash)
├── config/
│   └── hook.conf.example         # Шаблон конфига (без секретов)
├── deploy.sh                     # Деплой хука в GitLab bare-репо
└── README.md

Конфиг (hook.conf на сервере, не в репо)

bash
GITLAB_URL="https://gitlab.partizap.ru"
GITLAB_TOKEN="glpat-xxxx"
GITLAB_PROJECT_ID="1"
YOUTRACK_URL="https://youtrack.partizap.ru"
YOUTRACK_TOKEN="perm:xxxx"

Расположение хука на сервере

/var/opt/gitlab/git-data/repositories/<namespace>/<project>.git/custom_hooks/post-receive

Algorithm

foreach line in stdin:
  parse old_sha, new_sha, ref

  skip if: delete branch (new_sha = 0000...0)
  skip if: not refs/heads/* (tags, etc.)

  branch = ref без "refs/heads/"
  skip if: branch == "main" or "develop"

  task_id = первый match [A-Z]+-\d+ в branch
  skip if: не найден

  # YouTrack: проверяем задачу
  response = GET {YOUTRACK_URL}/api/issues/{task_id}?fields=summary
  if 404 or error:
    echo "⚠ Task {task_id} not found in YouTrack, MR not created"
    exit 0  # пуш всегда проходит

  task_summary = response.summary

  # GitLab: дедупликация
  existing = GET {GITLAB_URL}/api/v4/projects/{PROJECT_ID}/merge_requests
              ?source_branch={branch}&state=opened
  if existing не пустой:
    echo "ℹ MR already exists for {branch}"
    exit 0

  # Target branch
  target = "main" if branch starts with "hotfix/" else "develop"

  # GitLab: создаём MR
  POST {GITLAB_URL}/api/v4/projects/{PROJECT_ID}/merge_requests
    title: "{task_id}: {task_summary}"
    source_branch: branch
    target_branch: target
    remove_source_branch: true

  echo "✓ MR created: {task_id}: {task_summary} → {target}"

Edge Cases

КейсПоведение
Удаление веткиПропуск
Пуш в main/developПропуск
Нет task ID в имени веткиПропуск (без warning)
Задача не найдена в YouTrackWarning в output, пуш проходит
MR уже существует (opened)Info в output, пропуск
MR был закрыт/замерженСоздаётся новый MR
Несколько task ID в веткеБерётся первый
Пуш нескольких веток (--all)Обрабатывается каждая независимо
API недоступен (сеть, таймаут)Warning, пуш проходит
Таймаут APIcurl --max-time 5

YouTrack ↔ GitLab Integration

Хук создаёт MR. Связка MR ↔ задача в YouTrack обеспечивается встроенной VCS-интеграцией YouTrack:

  1. YouTrack → Administration → VCS Integrations → New → GitLab
  2. URL: https://gitlab.partizap.ru
  3. GitLab Personal Access Token (scopes: api, read_repository)
  4. Выбрать проекты для отслеживания

После этого YouTrack автоматически показывает коммиты и MR в карточке задачи.

Deploy

bash
# На VPS2:
cd partizap-hooks
./deploy.sh

deploy.sh копирует hooks/post-receive в custom_hooks директорию bare-репо и ставит chmod +x.

Future: Multi-repo

Для расширения на другие проекты:

  • Добавить массив target-директорий в deploy.sh
  • Или по конфигу на проект (hook.conf.frontend, hook.conf.backend)
  • Сам хук универсальный — PROJECT_ID берёт из конфига