PR 對話
Pull request 本來就是討論程式碼的地方。PR 對話把它變成 Control Center
工作區上的一個介面,就像聊天橋接把 Slack
變成介面一樣:在 PR 上 @提及伺服器的 GitHub App 機械人、在它的審查討論串內
回覆,或加上 ai-review 標籤,工作就會在 PR 的審查空間中進行——歸屬方式
和護欄都與在應用程式內輸入的任何內容相同。評論同樣受成員身分限制;標籤則
不受限,因為它沒有作者。機械人的答覆會回到 GitHub,就在問題所提出的同一條
渠道上。
三個決定塑造了這項功能,而每一個都是聊天橋接為聊天作過、再為程式碼託管 平台重述的同一個決定:連線往哪個方向走、來自外部的評論由甚麼授權, 以及對話每一方歸屬於誰。
輪詢就是傳輸方式
標題為「輪詢就是傳輸方式」的章節GitHub 為應用程式提供的唯一推送渠道是 webhook,而 webhook 需要一個入站 URL——這正是這個介面刻意從不要求的東西。因此探索靠一輪掃描:每隔約 一分鐘,每個應用程式安裝各自執行一次別名搜尋,向 GitHub 查詢提及機械人 (或其短 slug)的 PR,以及帶有審查標籤的開啟中 PR;已有審查空間的 PR 會 讀取其評論討論串,然後所有內容都以評論 id 與上次掃描所見的逐項比對。
設計上的幾個後果值得點名:
- 延遲是一個掃描週期,而不是一個事件。 👀 確認會在大約一分鐘內出現。 沒有急事會靠它。
- 每則評論恰好一次。 評論 id 在 GitHub 上是唯一的;每則評論在判定為 符合資格的那一刻就會被記錄,先於任何對它的處理。當機可能令某則評論的 處理遺失,但絕不會令它重複觸發。
- 離線期間的內容會補上,而不是重播。 已見集合會被持久保存,因此重新 啟動後會處理停機期間到達的內容。唯一的例外是史上第一次掃描:沒有記憶 可比對,所有未處理的項目都會靜靜記錄下來——在這部伺服器存在之前就為 二十個 PR 加上標籤的操作者,回來時不應該見到二十個正在執行的審查。
- 標籤是一個狀態,而不是一個事件。 搜尋報告的是標籤的_存在_,所以 一個已加標籤的 PR 只會觸發一次,僅此一次。移除標籤後再次加上,掃描並 不會察覺;要重跑就得靠提及。
搜尋會為每個安裝帳戶、以該擁有者自己的用戶端執行一次,因為安裝權杖只看 得到自己那次安裝的程式庫——單一個伺服器層級的憑證,會靜靜漏掉應用程式 其他安裝下的每個 PR。
授權的是成員身分,不是評論
標題為「授權的是成員身分,不是評論」的章節一則 PR 評論送達時,所帶的幾乎只有作者的登入名稱——一個未經認證的外部 身分,直到被證實為止。機械人會以工作區成員及其已連接 GitHub 帳戶的反向 索引來解析它;該索引會按 TTL 重建,因為伺服器執行期間有人會登入、有人會 受邀。
預設拒絕的做法像一道梯級,而每一級都會在被拒絕的那條討論串內作答:
- 未知的登入名稱——未連結,或由不是這個工作區成員的人連結——會被要求 登入並確認自己確實屬於此處
- 唯讀成員(
viewer或guest)會被告知其角色無法啟動工作
兩種未知登入的情況共用同一個回覆:反向索引只會傳回_這個_工作區的成員, 所以未連結的帳戶與已連結的非成員是同一種落空。它們都不會繼續。評論永遠 不會歸屬於沒有發出它的人,陌生人的話語也永遠不會進入他看不見的工作區。
ai-review 標籤沒有作者可解析,所以不會爬這道梯。加上它,就會在已經連結
該程式庫的工作區中啟動審查。
刻意採用兩個身分
標題為「刻意採用兩個身分」的章節對話的每一方都帶著不同的身分,而這個差異正是功能所在:
- 在 GitHub 上,機械人就是伺服器。 橋接所發佈的每則評論、表情反應和 回覆,都使用應用程式的安裝權杖。沒有任何人在用戶端點擊過任何東西, 所以不會借用個人帳戶——這條規則同樣令 webhook 和輪詢不倚賴人的憑證。
- 在空間內,問題屬於你。 訊息會歸屬於作者所解析到的成員,代理執行 也代表該成員進行:提交會把該成員列為共同作者,空間的自主調節與動作 護欄也完全如同對待應用程式內輸入的訊息一樣套用。執行期間對程式碼託管 平台的寫入,仍然以應用程式身分發出——與上一點的規則相同——而不是用 該成員的個人權杖。
把審查結果發佈回 GitHub 仍然是由人在 Control Center 所作的決定。提及可以 _啟動_一次審查;發佈則只能由人來做。
循環防護與短名稱
標題為「循環防護與短名稱」的章節任何由機械人帳戶撰寫的內容,都會在任何關卡執行之前被捨棄——包括我們自己
的機械人,以及所有帶 [bot] 後綴的帳戶,這樣其他應用程式的審查機械人也
無法喚醒我們的。沒有這道防護,機械人自己的答覆會以新評論的形式到達,令
它永遠重複觸發。
[bot] 後綴也是短格式存在的原因。GitHub 把應用程式帳戶的登入名稱固定為
<slug>[bot],不為它提供自動完成,也永遠不會把 @slug 解析到該應用
程式——所以接受只有 slug 的寫法是_我們的_比對器所作的決定,而要發現它,需要一條
直接搜尋評論文字的路徑,而不是 GitHub 的提及索引。這個代價會被明說,
而不是被含糊帶過:一個與應用程式 slug 相同的人類使用者,每次以短格式提及
自己時,都會同時向機械人發話。應用程式名稱夠獨特的話,這種衝突只是假設。
刻意不提供的功能
標題為「刻意不提供的功能」的章節- 不自動發佈。 審查結果會落在審查空間;發佈到 GitHub 是另一個由人 執行的動作
- 不做模糊身分。 作者只會解析到恰好一個成員,否則被拒絕——沒有猜測式 的歸屬
- 不用 GitHub App webhook。 這個介面從不註冊 webhook,所以沒有為 PR 評論而暴露的入站 URL。其他產品 webhook(管線、工單同步)屬於另一項 選用設定。
另請參閱
標題為「另請參閱」的章節- 從 GitHub PR 與 Control Center 對話: 以上一切的操作指南
- 聊天橋接:同樣的三個決定,這次是為聊天而作
- 建立 GitHub App:機械人身分的來源
- 多人協作——身分、成員資格與線上狀態: 登入名稱所解析的主體與角色
- 護欄:負責回答的代理可以做甚麼
- 使用 AI 輔助審查:提及或標籤所啟動的 管線