Разговоры в PR
Pull request — это уже то место, где происходит разговор о коде. Разговоры в PR
делают его поверхностью рабочего пространства Control Center — так же, как
чат-мост делает такой поверхностью Slack:
упомяните бота GitHub App вашего сервера через @ на PR, ответьте внутри его веток
ревью или добавьте метку ai-review — и работа произойдёт в пространстве проверки
этого PR, с тем же закреплением авторства и теми же ограничениями, что и всё,
набранное в приложении. Комментарий вдобавок проходит проверку на членство;
метка — нет, потому что у неё нет автора. Ответы бота возвращаются в GitHub,
в ту самую ветку, где был задан вопрос.
Три решения определяют эту возможность, и каждое из них — то же решение, которое чат-мост принял для чата, только пересказанное для хоста кода: в каком направлении идёт соединение, что подтверждает права комментария, пришедшего извне, и за кем закрепляется каждая сторона.
Транспорт — это опрос
Заголовок раздела «Транспорт — это опрос»Единственный push-канал для приложения в GitHub — это вебхук, а вебхуку нужен входящий URL — единственное, чего эта поверхность намеренно никогда не требует. Поэтому обнаружение — это обход: примерно раз в минуту один поисковый запрос с псевдонимом на каждую установку приложения спрашивает у GitHub о PR, которые упоминают бота (или его короткий slug), и об открытых PR, несущих метку проверки; у PR, которые уже имеют пространство проверки, читаются ветки комментариев; а всё остальное сравнивается по id комментария с тем, что было увидено в прошлый обход.
Последствия этого решения стоит назвать:
- Задержка — это интервал обхода, а не событие. Подтверждение 👀 появляется примерно в течение минуты. Ничего срочного на этом не держится.
- Ровно один раз на комментарий. Идентификаторы комментариев уникальны во всём GitHub; каждый записывается в тот момент, когда признан подходящим, — до того, как по нему что-либо предпринимается. Сбой может потерять обработку комментария, но никогда не запустит её дважды.
- Простой догоняется, а не воспроизводится заново. Набор увиденного сохраняется, поэтому после перезапуска доставляется то, что пришло во время простоя. Единственное исключение — самый первый обход: сравнивать не с чем, поэтому всё необработанное записывается молча, — оператор, пометивший двадцать PR до появления этого сервера, не должен вернуться к двадцати запущенным проверкам.
- Метка — это множество, а не событие. Поиск сообщает о наличии метки, поэтому помеченный PR срабатывает один раз и навсегда. Повторное добавление метки после удаления для обхода невидимо; путь к повторному запуску — упоминание.
Поиск выполняется по одному разу на каждый аккаунт установки, через собственный клиент этого владельца: токен установки видит только репозитории своей установки, — а единая учётная запись на весь сервер молча пропускала бы каждый PR под другими установками приложения.
Авторизует членство, а не комментарий
Заголовок раздела «Авторизует членство, а не комментарий»Комментарий в PR приходит, неся немногим больше логина автора, — неаутентифицированная внешняя идентичность, пока не доказано обратное. Бот сопоставляет его с обратным индексом участников рабочего пространства и их подключённых аккаунтов GitHub; индекс перестраивается по TTL, потому что люди входят в систему и получают приглашения, пока сервер работает.
Отказ при неопределённости выглядит как лестница, и каждая её ступень отвечает в той самой ветке, где отказала:
- Неизвестный логин — не привязан или привязан тем, кто не состоит в этом рабочем пространстве, — получает совет войти и убедиться, что он относится к этому рабочему пространству
- Участник только для чтения (
viewerилиguest) получает ответ, что его роль не позволяет запускать работу
Два случая с неизвестным логином получают один и тот же ответ: обратный индекс возвращает только участников этого рабочего пространства, поэтому непривязанный аккаунт и привязанный не-участник — один и тот же промах. Ни один из них не продолжает. Комментарий никогда не приписывается тому, кто его не отправлял, и слова постороннего никогда не попадают в рабочее пространство, которое он не видит.
У метки ai-review нет автора, которого можно сопоставить, поэтому по этой
лестнице она не поднимается. Её добавление запускает проверку в том рабочем
пространстве, которое уже привязало репозиторий.
Две идентичности — намеренно
Заголовок раздела «Две идентичности — намеренно»Каждая сторона разговора несёт свою идентичность, и эта разница — и есть суть возможности:
- В GitHub бот — это сервер. Каждый комментарий, реакция и ответ, которые публикует мост, уходят от токена установки приложения. Никто ничего не нажимал в клиенте, поэтому ничто не одалживает аккаунт человека — то же правило, которое не даёт вебхукам и опросу работать от человеческих учётных данных.
- В пространстве вопрос принадлежит вам. Сообщение приписывается участнику, с которым сопоставлен автор, и запуск агента выполняется от его имени: коммиты указывают его соавтором, а регулятор автономии и ограничения действий пространства применяются ровно так же, как к сообщению, набранному в приложении. Записи в хост кода из этого запуска по-прежнему уходят от имени приложения — то же правило, что и в пункте выше, — а не от личного токена участника.
Публикация замечаний проверки обратно в GitHub остаётся решением человека, принятым в Control Center. Упоминание может запустить проверку; публикует её только человек.
Защита от циклов и короткое имя
Заголовок раздела «Защита от циклов и короткое имя»Всё, что написано аккаунтом бота, отбрасывается до того, как сработает любой
шлюз, — и наш конкретно, и любой суффикс [bot], чтобы бот-ревьюер другого
приложения тоже не мог разбудить нашего. Без этого собственные ответы бота
приходили бы как новые комментарии и зацикливали бы его навсегда.
Суффикс [bot] — ещё и причина, по которой существует короткая форма. GitHub
жёстко закрепляет логин аккаунта приложения как <slug>[bot], не предлагает для
него автодополнение и никогда не сопоставляет @slug с приложением, — поэтому
приём голого slug — это решение нашего сопоставителя, а для его обнаружения
нужна отдельная полоса поиска по необработанному тексту комментариев, а не
индекс упоминаний GitHub. Цена названа, а не сглажена: человек, чей логин
совпадает со slug приложения, обращается к боту каждым коротким упоминанием
самого себя. Отличительные имена приложений делают такое совпадение
гипотетическим.
Что намеренно не предлагается
Заголовок раздела «Что намеренно не предлагается»- Никакой автопубликации. Замечания попадают в пространство проверки; публикация в GitHub — отдельное действие, которое выполняет человек
- Никакого нечёткого сопоставления. Автор сопоставляется ровно с одним участником или получает отказ — авторства «на глаз» не бывает
- Никакого вебхука GitHub App. Эта поверхность никогда его не регистрирует, поэтому входящего URL для комментариев в PR не существует. Другие вебхуки продукта (конвейеры, синхронизация тикетов) — отдельная необязательная настройка.
См. также
Заголовок раздела «См. также»- Общаться с Control Center из GitHub PR: руководство по всему этому
- Чат-мосты: те же три решения, принятые для чата
- Создать GitHub App: откуда берётся идентичность бота
- Совместная работа — идентичность, членство и присутствие: участники и роли, через которые сопоставляется логин
- Ограничения: что разрешено отвечающему агенту
- Использовать ИИ-проверку: конвейер, который запускает упоминание или метка