Skip to Content
Руководство для пользователейВозможностиКаналыGitLab

GitLab

В этом руководстве описана настройка канала Qwen Code для мониторинга todos в GitLab и ответа на упоминания в issues и merge requests.

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

  • Аккаунт GitLab (или выделенный аккаунт бота)
  • Персональный токен доступа GitLab (Personal Access Token) со скоупами read_api и api

Создание токена

  1. Перейдите в Preferences → Access Tokens
  2. Создайте токен со следующими скоупами:
    • read_api — чтение todos и данных проекта
    • api — публикация заметок (комментариев) к issues/MRs
  3. Сохраните токен в переменную окружения

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

Добавьте канал в ~/.qwen/settings.json:

{ "channels": { "my-gitlab": { "type": "gitlab", "token": "$GITLAB_TOKEN", "pollInterval": 60000, "senderPolicy": "open", "sessionScope": "chat_thread", "cwd": "/path/to/your/project", "groupPolicy": "open", "action_prompt_template": { "mentioned": "Project: %project% | URL: %project_url% | Author: %author% | Type: %target_type% | IID: %iid% | Title: %title% | Description: %description% | TodoID: %todo_id%" } } } }

Установите токен как переменную окружения:

export GITLAB_TOKEN="glpat-your_token_here"

Self-hosted GitLab

Для self-hosted инстансов укажите baseUrl:

{ "baseUrl": "https://gitlab.example.com" }

Параметры конфигурации

ПараметрЗначение по умолчаниюОписание
token(обязательно)PAT со скоупами read_api + api
pollInterval60000Интервал опроса в мс
baseUrlhttps://gitlab.comURL инстанса GitLab
action_prompt_template(обязательно для обработки)Сопоставляет имена действий GitLab с шаблонами метаданных
groupPolicy"disabled"Должен быть "open" или "allowlist" с указанием проекта
senderPolicy"allowlist"Кто может запускать бота

action_prompt_template

Это поле определяет, какие действия todo обрабатываются и как формируются метаданные. Обрабатываются только те действия, для которых задан шаблон; остальные пропускаются и помечаются как выполненные.

{ "action_prompt_template": { "mentioned": "Project: %project% | Author: %author% | Title: %title%" } }

Действие directly_addressed (комментарий, начинающийся с @bot) автоматически использует фолбэк на шаблон mentioned, если не настроено явно.

Доступные ключи действий

КлючТриггер
mentionedКто-то @упоминает бота в комментарии или описании (не в начале)
directly_addressedКомментарий начинается с @bot (фолбэк на шаблон mentioned)
assignedКто-то назначает бота на issue/MR
review_requestedКто-то запрашивает бота как ревьюера на MR
approval_requiredMR требует одобрения бота (правила одобрения)
markedКто-то помечает комментарий/issue/MR бота (звёздочка)
build_failedCI/CD пайплайн завершился ошибкой на ветке/MR бота
unmergeableMR, в котором участвует бот, становится неслияемым (конфликты)
merge_train_removedMR удалён из merge train

Обрабатываются только те ключи, которые присутствуют в action_prompt_template. Необработанные действия пропускаются и молча помечаются как выполненные.

Переменные шаблона

ПеременнаяЗначение
%project%Путь проекта (например, owner/repo)
%project_url%Полный URL проекта
%author%Имя пользователя автора todo
%target_type%Issue или MergeRequest
%iid%Внутренний ID issue/MR
%title%Заголовок issue/MR
%description%Тело описания issue/MR
%todo_id%ID todo в GitLab
%%Литеральный символ % (экранирование)

Неизвестные переменные сохраняются в выходных данных как есть.

Сборка промпта

Шаблон рендерится в envelope.metadata (структурированный контекст). Текст триггера (todo.body или описание) попадает в envelope.text (основной промпт). Базовый класс собирает итоговый промпт, отправляемый агенту:

[alice] please fix this bug Project: owner/repo | URL: https://gitlab.com/owner/repo | Author: alice | Type: Issue | IID: 42 | Title: Test Issue | Description: ... | TodoID: 100
  • Строка 1: префикс [sender] + envelope.text (с удалённым @bot)
  • Строка 3: envelope.metadata (отрендеренный шаблон, очищенный)

Переменная %body% не нужна — текст комментария/описания всегда является основным содержимым промпта, а шаблон предоставляет дополнительный контекст ниже.

⚠️ Безопасность

В публичном проекте при senderPolicy: "open" любой пользователь GitLab, упомянувший бота через @, может отправлять промпты, управляющие агентом в вашем cwd.

Всегда используйте senderPolicy: "allowlist" с явным указанием allowedUsers в публичных проектах.

Обнаружение упоминаний

Адаптер всегда устанавливает isMentioned = true для отправляемых envelope-объектов, потому что GitLab уже определил упоминание при создании todo. Конфигурация action_prompt_template является реальным фильтром событий — обрабатываются только действия с настроенным шаблоном. Упоминание @bot удаляется из текста сообщения перед отправкой через stripBotMention.

⚠️ groupPolicy должен быть “open” или “allowlist”

Для обработки todos параметр groupPolicy должен быть установлен в "open" или "allowlist" с явным указанием проекта. Значение по умолчанию "disabled" отклоняет все упоминания: todos помечаются как выполненные, курсор продвигается, но отправка не происходит. В лог записывается отклонение (preflight rejected reason=group_disabled), но todo всё равно считается обработанным. Если бот не отвечает на упоминания, проверьте, что groupPolicy не установлен в "disabled".

Как это работает

Адаптер использует GitLab Todos API как источник сообщений:

  1. Опрос GET /todos?state=pending для получения новых todos
  2. Первичная очистка: если курсор никогда не инициализировался (initialized: false), все ожидающие todos помечаются как выполненные без отправки, и курсор продвигается до максимального ID todo. Это предотвращает завал отложенных задач при первом запуске.
  3. Очистка устаревших todos: todos с id <= cursor помечаются как выполненные (best-effort), чтобы предотвратить их повторную выборку при каждом опросе
  4. Фильтрация по id > cursor и настроенному action_prompt_template
  5. Определение типа упоминания по якорю target_url:
    • #note_123 присутствует → упоминание в комментарии → текст: todo.body (комментарий)
    • Нет якоря → упоминание в описании → текст: описание issue/MR
  6. Отправка envelope через handleInbound (требуется groupPolicy: "open" или "allowlist" с указанием проекта)
  7. Продвижение курсора и пометка todo как выполненного (best-effort)

Курсор (lastProcessedId) продвигается независимо от успеха или неудачи отправки. При неудачной отправке в issue/MR добавляется комментарий с ⚠️ об ошибке; повторных попыток не делается — пользователь может повторно упомянуть бота, чтобы создать новый todo.

Обратная связь через реакции

При принятом упоминании в комментарии (заметка с якорем #note_) канал добавляет award emoji 👀 к заметке, пока агент работает, а затем удаляет его при завершении, ошибке или отмене. Обе операции выполняются в режиме best-effort: ошибка API award emoji или нехватка прав логируется и никогда не блокирует финальный ответ.

Упоминания в описании (без якоря #note_) не получают award emoji, потому что нет конкретной заметки для реакции.

Известные ограничения

  • При первом запуске существующие ожидающие todos пропускаются. Курсор инициализируется как { lastProcessedId: 0, initialized: false } при первом запуске. При первом цикле опроса все ранее существовавшие ожидающие todos помечаются как выполненные без отправки (флаг initialized обеспечивает эту одноразовую очистку), предотвращая завал отложенных задач.
  • Бот не читает историю предыдущих обсуждений — обрабатывается только содержимое триггера.
  • Конфиденциальные (внутренние) заметки: если кто-то @упоминает бота в конфиденциальной заметке, тело todo содержит этот внутренний текст, и агент его обработает. Ответ бота всегда публикуется как публичная заметка, что может раскрыть внутреннее обсуждение. Todo API GitLab не предоставляет информацию о видимости заметок, поэтому адаптер не может это отфильтровать. Не упоминайте бота через @ в конфиденциальных заметках.
  • Требуются скоупы PAT read_api + api. Токены на уровне группы или проекта работают, если имеют эти скоупы.
  • Todos для Epics, Designs и Alerts пропускаются (обрабатываются только Issues и MRs).

Запуск канала

qwen channel start my-gitlab
Last updated on