Розмови в PR
Pull request — це вже те місце, де точиться розмова про код. Розмови в PR
роблять його такою самою поверхнею робочого простору Control Center, якою
чат-міст робить Slack: @-згадайте
бота GitHub App цього сервера в PR, дайте відповідь у його обговореннях рев’ю
або додайте мітку ai-review — і робота відбувається в просторі рев’ю цього
PR, під тією самою атрибуцією й тими самими обмеженнями, що й будь-що набране
в застосунку. Коментар також вимагає членства; мітка — ні, бо в неї немає
автора. Відповіді бота повертаються на GitHub — в те саме обговорення, де
прозвучало запитання.
Функцію формують три рішення, і кожне з них — те саме рішення, яке чат-міст ухвалив для чату, переказане для forge: у якому напрямку встановлюється з’єднання, що авторизує коментар, який надходить ззовні, і кому приписується кожен бік.
Транспорт — це опитування
Розділ із назвою «Транспорт — це опитування»Єдиний push-канал, який GitHub надає застосунку, — це webhook, а webhook потребує вхідного URL — саме того, чого ця поверхня свідомо ніколи не вимагає. Тож виявлення — це прохід: приблизно щохвилини один пошук за аліасом на кожну інсталяцію застосунку запитує в GitHub PR, які згадують бота (або його короткий slug), і відкриті PR із міткою рев’ю; у PR, які вже мають простір рев’ю, читаються обговорення їхніх коментарів, а все порівнюється за id коментаря з тим, що бачили під час минулого проходу.
Наслідки такого рішення варто назвати:
- Затримка — це інтервал між проходами, а не подія. Реакція 👀 з’являється приблизно за хвилину. Нічого термінового на цьому не тримається.
- Рівно один раз на коментар. Ідентифікатори коментарів унікальні в межах усього GitHub; кожен записується тієї ж миті, коли його визнано придатним, — ще до того, як щось почне з ним діяти. Аварійне завершення може втратити опрацювання коментаря, але ніколи не запустить його двічі.
- Час офлайну надолужується, а не відтворюється. Набір побаченого зберігається на диску, тож після перезапуску доставляється все, що надійшло, поки сервер не працював. Єдиний виняток — найперший прохід: коли немає пам’яті, з чим порівнювати, усе наявне тихо фіксується — оператор, який позначив двадцять PR ще до появи цього сервера, не повинен повернутися до двадцяти запущених рев’ю.
- Мітка — це множина, а не подія. Пошук повідомляє про наявність мітки, тож позначений PR запускається один раз — і більше ніколи. Повторне додавання мітки після її зняття прохід не помічає; щоб запустити знову, потрібна згадка.
Пошук виконується один раз на кожен обліковий запис інсталяції, клієнтом самого власника, бо токен інсталяції бачить лише репозиторії власної інсталяції — єдині облікові дані на весь сервер непомітно пропустили б кожен PR під іншими інсталяціями застосунку.
Авторизує членство, а не коментар
Розділ із назвою «Авторизує членство, а не коментар»Коментар у PR приходить, несучи хіба що логін автора — неавтентифіковану зовнішню ідентичність, доки її не підтверджено. Бот зіставляє його зі зворотним індексом учасників робочого простору та пов’язаних із ними облікових записів GitHub, який перебудовується за TTL, бо люди входять і отримують запрошення, поки сервер працює.
Відмова за замовчуванням виглядає як драбина, і кожна її сходинка відповідає в тому обговоренні, де відмовила:
- Невідомий логін — не пов’язаний або пов’язаний особою, яка не є учасником цього робочого простору, — отримує підказку увійти й переконатися, що він справді належить до простору
- Учасник із доступом лише для читання (
viewerабоguest) отримує відповідь, що його роль не дозволяє починати роботу
Обидва випадки невідомого логіна отримують одну відповідь: зворотний індекс повертає лише учасника цього робочого простору, тож непов’язаний обліковий запис і пов’язаний не-учасник — це той самий промах. Жоден із них не продовжує роботу. Коментар ніколи не приписується тому, хто його не надсилав, і слова сторонньої людини ніколи не потрапляють у робочий простір, якого вона не бачить.
У мітки ai-review немає автора, якого можна було б зіставити, тож вона не
піднімається цією драбиною. Її додавання запускає рев’ю в робочому просторі, який
уже пов’язаний із репозиторієм.
Дві ідентичності — навмисно
Розділ із назвою «Дві ідентичності — навмисно»Кожен бік розмови несе різну ідентичність, і саме ця різниця й є суттю функції:
- На GitHub бот — це сервер. Кожен коментар, реакція й відповідь, які публікує міст, ідуть під токеном інсталяції застосунку. Ніхто нічого не натискав у клієнті, тож ніщо не позичає обліковий запис людини — те саме правило, яке тримає webhooks і опитування подалі від людських облікових даних.
- У просторі запитання — ваше. Повідомлення приписується тому учаснику, яким виявився автор, і запуск агента виконується від його імені: коміти зазначають його співавтором, а регулятор автономності простору й обмеження дій застосовуються так само, як до повідомлення, набраного в застосунку. Записи у forge з цього запуску все одно йдуть від імені застосунку — те саме правило, що й у пункті вище, — а не під особистим токеном учасника.
Публікація знахідок рев’ю назад на GitHub залишається рішенням людини, ухваленим у Control Center. Згадка може запустити рев’ю; публікує його лише людина.
Захист від зациклення та коротка назва
Розділ із назвою «Захист від зациклення та коротка назва»Усе, створене обліковим записом бота, відкидається ще до того, як спрацює
будь-який шлюз — і наш власний, і будь-який суфікс [bot], щоб бот рев’ю іншого
застосунку теж не міг розбудити нашого. Без цього власні відповіді бота приходили
б як нові коментарі й запускали б його знову й знову.
Суфікс [bot] — це також причина існування короткої форми. GitHub закріплює
логін облікового запису застосунку як <slug>[bot], не пропонує для нього
автодоповнення й ніколи не розпізнає @slug як застосунок — тож рішення
приймати голий slug ухвалює наш механізм зіставлення, а для його виявлення
потрібен окремий канал пошуку за власне текстом коментаря, а не за індексом
згадок GitHub. Ціну названо прямо, а не згладжено: людина-користувач, чий slug
збігається зі slug застосунку, звертається до бота кожною короткою згадкою самої
себе. Виразні назви застосунків роблять такий збіг суто гіпотетичним.
Що свідомо не пропонується
Розділ із назвою «Що свідомо не пропонується»- Жодної автопублікації. Знахідки потрапляють у простір рев’ю; публікація на GitHub — окрема дія, яку виконує людина
- Жодної нечіткої ідентичності. Автор зіставляється рівно з одним учасником або отримує відмову — атрибуції за здогадом не існує
- Жодного webhook GitHub App. Ця поверхня ніколи його не реєструє, тож немає вхідного URL, який треба було б відкривати для коментарів у PR. Інші webhooks продукту (конвеєри, синхронізація тікетів) налаштовуються окремо й необов’язково.
Дивіться також
Розділ із назвою «Дивіться також»- Спілкуватися з Control Center з GitHub PR: практичний посібник з усього цього
- Чат-мости: ті самі три рішення, ухвалені для чату
- Створити GitHub App: звідки береться ідентичність бота
- Спільна робота — ідентичність, членство та присутність: принципали й ролі, через які розпізнається логін
- Обмеження: що дозволено агенту, який відповідає
- Використовувати ШІ-перевірку: конвеєр, який запускає згадка або мітка