Интеграция GitHub
Подключите GitHub App один раз — PR, в ветке, заголовке или теле которого есть идентификатор issue, автоматически привяжется к этому issue, а merge PR переведёт issue в Done.
Подключите аккаунт или организацию GitHub один раз в Settings → GitHub. После этого любой pull request, в имени ветки, заголовке или теле которого есть идентификатор issue (например MUL-123), автоматически связывается с этим issue, появляется в блоке Pull requests на боковой панели issue и — при merge PR — переводит issue в Done.
Отдельной настройки на каждый issue нет. Весь поток строится на идентификаторах.
Что делает интеграция
| Поверхность | Поведение |
|---|---|
| Settings → GitHub | Администраторы workspace видят вкладку GitHub с master toggle, кнопкой Connect GitHub и переключателями функций (PR sidebar, Co-authored-by, auto-link). После установки вы возвращаетесь на вкладку GitHub. |
| Issue sidebar → Pull requests | Все PR, автоматически связанные с этим issue: заголовок, repo, состояние (Open / Draft / Merged / Closed) и автор. Клик по строке открывает PR на GitHub. |
| Webhook (фон) | На каждое событие pull_request Multica upsert-ит строку PR, сканирует PR на идентификаторы issue и (пере)строит строки связей. Идемпотентно — повторная доставка — no-op. |
| Auto-status при merge | Когда PR переходит в merged, каждый связанный issue, ещё не в Done или Cancelled, переводится в Done. Смена статуса попадает в timeline с источником github_pr_merged. |
Зеркалируется только сам PR. Commits, ссылки на ветки без открытого PR и состояния CI checks не моделируются. Интеграция намеренно узкая.
Как сопоставляются идентификаторы
Webhook извлекает идентификаторы из трёх полей в таком порядке: PR head branch, PR title, PR body. Matcher:
- Без учёта регистра —
mul-123,MUL-123,Mul-123совпадают. - С границами —
\bслева и digit anchor справа не дают захватить номера версий вродеv1.2-3или строки в стиле email. - В пределах workspace — совпадает только issue prefix этого workspace.
FOO-1в workspace с префиксомMULигнорируется, даже если число совпадает с другим issue. - С дедупликацией —
MUL-1, MUL-1в body связывает issue один раз.
В одном PR можно сослаться на несколько issue. Closes MUL-1, MUL-2 связывает PR с обоими, и merge переводит оба в Done.
Правило auto-merge в Done
Когда поле merged у PR становится true, оценивается каждый связанный issue:
| Текущий статус issue | Результат |
|---|---|
done | Без изменений (уже терминальный). |
cancelled | Без изменений — cancelled значит, что вы явно отказались от работы; интеграция этот сигнал не перебивает. |
Всё остальное (todo, in_progress, in_review, blocked, backlog) | Перевод в done. |
Закрытие PR без merge только обновляет состояние карточки PR на Closed. Связанные issue остаются как были — смысл «закрыть без merge» решаете вы.
Действие в timeline приписывается актору system. Подписчики issue получают уведомление в inbox о смене статуса — так же, как если бы статус сменил человек.
Что не связывается автоматически
- Идентификаторы в commit messages — сканируются только branch / title / body. Commit с текстом
MUL-123: fix loginне свяжется, если та же строка не есть в title или body PR. - Идентификаторы в комментариях PR — сканируются только метаданные самого PR; последующие комментарии на GitHub игнорируются.
- PR в repo, где App не установлен — без App Multica не получит webhook.
- Ручная привязка PR к issue — UI для этого пока нет. Если команда кладёт идентификаторы туда, откуда Multica не читает, добавьте их в title или body PR.
Отключение
В Settings → GitHub нет списка установок — существующими установками управляете напрямую на GitHub:
- С GitHub — удалите Multica GitHub App на
https://github.com/settings/installations(личный аккаунт) илиhttps://github.com/organizations/<org>/settings/installations(org). Multica получит webhookinstallation.deletedи удалит строку в реальном времени; открытая вкладка Settings обновится без refresh. - Disconnect из Multica — только для admin — кнопка Disconnect на вкладке GitHub скрыта для не-admin. Она доступна даже когда master switch GitHub выключен, чтобы admin мог отозвать устаревшую установку после одношагового отключения функции.
После disconnect зеркалированные строки PR остаются в базе — исторические sidebar issue сохраняют связи, но новые webhook-события от этой установки не принимаются.
Права и видимость
- Connect / disconnect требуют роли workspace owner или admin. Members видят описание карточки, но не кнопку Connect.
- Блок Pull requests на issue виден всем, кто может читать issue — те же права, что и на остальную деталь issue.
- GitHub App запрашивает read-only доступ к pull requests и metadata. Multica не пушит commits, comments и status checks обратно на GitHub.
Настройка self-host
На Multica Cloud интеграция уже настроена — этот раздел можно пропустить.
Для self-host создаёте один GitHub App, указываете на свой server и задаёте две переменные окружения. Полный поток ниже.
1. Создайте GitHub App
Перейдите на один из адресов:
- Личный аккаунт →
https://github.com/settings/apps/new - Organization →
https://github.com/organizations/<org>/settings/apps/new
Заполните:
| Поле | Значение |
|---|---|
| GitHub App name | Любое узнаваемое имя, например Multica или Multica (staging). |
| Homepage URL | Frontend Multica, например https://multica.example.com. |
| Callback URL | Оставьте пустым — Multica не использует OAuth user identity. |
| Setup URL | https://<api-host>/api/github/setup. Включите «Redirect on update». |
| Webhook → Active | Enabled. |
| Webhook URL | https://<api-host>/api/webhooks/github. |
| Webhook secret | Длинная случайная строка (например openssl rand -hex 32). То же значение вставите в env Multica на шаге 2. |
| Permissions → Repository → Pull requests | Read-only. |
| Permissions → Repository → Metadata | Read-only (обязательно). |
| Subscribe to events | Отметьте Pull request. |
| Where can this GitHub App be installed? | На ваш выбор. Only on this account подходит для single-org. |
После Create GitHub App запишите с страницы App:
- Public link вверху — хвост URL это slug.
https://github.com/apps/multica-acme→ slug =multica-acme. - Webhook secret, который вы только что сгенерировали (GitHub потом не покажет его снова — сохраните сейчас).
Webhook secret ≠ Client secret. На странице настроек App оба поля рядом. Webhook secret подписывает payload pull_request — его и нужен Multica. Client secret для OAuth и этой интеграцией не используется. Перепутать их — получить 401 invalid signature на каждой доставке webhook.
2. Задайте переменные окружения
На API server:
GITHUB_APP_SLUG=multica-acme
GITHUB_WEBHOOK_SECRET=<the webhook secret you generated>
# Optional but recommended — populates the connected account name on
# install instead of waiting for the first webhook to refresh it:
GITHUB_APP_ID=<numeric App ID from the App's settings page>
GITHUB_APP_PRIVATE_KEY=<full PEM block, including BEGIN/END lines>GITHUB_APP_SLUG и GITHUB_WEBHOOK_SECRET обязательны. Если одной из них нет:
- Connect GitHub в Settings отключён и показывает подсказку «not configured».
- Endpoint
/api/webhooks/githubвозвращает503 github webhooks not configured— Multica не обрабатывает события без secret, а не молча считает любую подпись валидной.
GITHUB_APP_ID и GITHUB_APP_PRIVATE_KEY опциональны. Setup callback может вызвать App-authenticated endpoint GitHub /app/installations/{id} и сразу получить имя org или user при install. Без них карточка подключения кратко показывает Connected to unknown, пока GitHub не доставит webhook installation.created (обычно за несколько секунд); Multica обновит строку и разошлёт realtime update — открытая вкладка Settings обновится без ручного refresh. Private key: Private keys → Generate a private key на странице App; вставьте полный PEM-блок (включая строки -----BEGIN/END RSA PRIVATE KEY-----) в env var, сохранив переносы строк.
FRONTEND_ORIGIN тоже должен быть задан (для production self-host он уже есть); setup callback возвращает пользователя на <FRONTEND_ORIGIN>/settings?tab=github после install.
Перезапустите API после задания env vars.
3. Запустите migrations
Таблицы интеграции в migration 079_github_integration. При upgrade старого deployment:
make migrate-upСоздаются три таблицы: github_installation, github_pull_request, issue_pull_request. Они cascade-delete вместе с workspace — удаление workspace очищает их автоматически.
4. Подключите из UI
В Multica:
- Откройте Settings → GitHub как owner или admin.
- Нажмите Connect GitHub. GitHub откроется в новой вкладке.
- Выберите repo для доступа и Install.
- GitHub перенаправит на
<api-host>/api/github/setup, который запишет installation и вернёт вас на<FRONTEND_ORIGIN>/settings?tab=github&github_connected=1.
После этого откройте любой PR, в branch / title / body которого есть идентификатор issue — через несколько секунд блок Pull requests появится на странице этого issue.
5. Проверка curl probe
Если на GitHub Recent Deliveries после install показывает 401 invalid signature, secret на двух сторонах различается. Быстрее всего проверить, обойдя GitHub:
SECRET="<the value you put in GITHUB_WEBHOOK_SECRET>"
BODY='{"zen":"test"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')
curl -i -X POST https://<api-host>/api/webhooks/github \
-H "X-Hub-Signature-256: sha256=$SIG" \
-H "X-GitHub-Event: ping" \
-H "Content-Type: application/json" \
-d "$BODY"| HTTP status | Значение | Исправление |
|---|---|---|
200 {"ok":"pong"} | Secret в процессе совпадает с вашим $SECRET. Несовпадение на стороне GitHub. | App → Webhook secret → вставьте то же значение → Save changes (клик вне поля без Save оставляет старый secret). Redeliver. |
401 invalid signature | Secret в процессе не тот, что вы думаете. | Убедитесь, что env var попал в running process (например kubectl exec → `echo -n "$GITHUB_WEBHOOK_SECRET" |
503 github webhooks not configured | GITHUB_WEBHOOK_SECRET пуст в процессе. | Задайте env var, перезапустите API. |
Ограничения
Несколько шероховатостей на сегодня:
- Ручной link UI пока нет — единственный способ связать PR — идентификатор в branch, title или body.
- Нет CI / check state — зеркалируется только PR. Build status, review comments и reviewers в Multica не показываются.
- Нет workspace-level config для правила merge → Done — фиксированный default (
merged → done, кромеcancelled). Настраиваемые mapping — в планах. - Несколько PR на один issue — консервативно при merge — если два PR ссылаются на
MUL-123и первый merge-ится, issue сразу переходит вDone. Ожидание merge всех связанных PR перед advance — в работе.
Далее
- Issues — идентификаторы issue (
MUL-123) из PR - Workspaces — где задаётся issue prefix workspace
- Environment variables — полный справочник env, включая GitHub variables выше