Zum Inhalt springen

PR-Unterhaltungen

Ein Pull Request ist schon der Ort, an dem das Gespräch über Code stattfindet. PR-Unterhaltungen machen ihn zu einer Oberfläche auf einem Arbeitsbereich von Control Center, so wie eine Chat-Brücke Slack zu einer macht: den Bot der GitHub App des Servers auf einem PR mit @ erwähnen, in seinen Review-Threads antworten oder das Label ai-review setzen, und die Arbeit läuft im Review-Bereich des PR — unter derselben Zuschreibung und denselben Schutzregeln wie alles, was in der App getippt wird. Ein Kommentar hängt zusätzlich an der Mitgliedschaft; das Label nicht, weil es keinen Autor hat. Die Antworten des Bots kommen auf GitHub zurück, in der Spur, in der die Frage gestellt wurde.

Drei Entscheidungen prägen die Funktion, und jede ist dieselbe Entscheidung, die die Chat-Brücke für den Chat getroffen hat, hier für eine Forge neu formuliert: in welche Richtung die Verbindung läuft, was einen Kommentar autorisiert, der von außen ankommt, und wem jede Seite zugeschrieben wird.

Der einzige Push-Kanal, den GitHub einer App bietet, ist ein Webhook, und ein Webhook braucht eine eingehende URL — genau das, was diese Oberfläche bewusst nie verlangt. Die Erkennung ist deshalb ein Durchlauf: ungefähr jede Minute fragt eine Suche mit Alias je App-Installation GitHub nach Pull Requests, die den Bot erwähnen (oder seinen kurzen Slug), und nach offenen Pull Requests mit dem Review-Label. Pull Requests, die schon einen Review-Bereich haben, werden auf ihre Kommentar-Threads gelesen, und alles wird anhand der Kommentar-ID gegen den letzten Durchlauf abgeglichen.

Die Folgen des Entwurfs lohnt es zu benennen:

  • Die Latenz ist ein Durchlaufintervall, kein Ereignis. Die Bestätigung 👀 trifft innerhalb von etwa einer Minute ein. Nichts Dringendes hängt daran.
  • Genau einmal, je Kommentar. Kommentar-IDs sind auf ganz GitHub eindeutig; jede wird in dem Moment festgehalten, in dem sie als zulässig gilt, bevor irgendetwas darauf reagiert. Ein Absturz kann die Bearbeitung eines Kommentars verlieren, ihn aber nie doppelt auslösen.
  • Ausfallzeit wird nachgeholt, nicht erneut abgespielt. Die Menge der gesehenen IDs bleibt gespeichert, ein Neustart liefert also, was während des Ausfalls ankam. Die eine Ausnahme ist der allererste Durchlauf: ohne Gedächtnis für den Abgleich wird alles Offene still festgehalten — wer zwanzig Pull Requests markiert hat, bevor es diesen Server gab, darf nicht zu zwanzig laufenden Reviews zurückkehren.
  • Das Label ist eine Menge, kein Ereignis. Die Suche meldet die Anwesenheit des Labels, ein markierter Pull Request löst also einmal aus, für immer. Ein Label nach dem Entfernen wieder zu setzen bleibt für den Durchlauf unsichtbar; eine Erwähnung ist der Weg zum erneuten Lauf.

Die Suche läuft einmal je Installationskonto auf dem eigenen Client dieses Inhabers, weil ein Installationstoken nur die Repos seiner eigenen Installation sieht — ein einziges serverweites Zugangsdatum würde still jeden Pull Request unter den übrigen Installationen der App verpassen.

Die Mitgliedschaft autorisiert, nicht der Kommentar

Abschnitt betitelt „Die Mitgliedschaft autorisiert, nicht der Kommentar“

Ein PR-Kommentar kommt mit kaum mehr an als dem Login des Autors — einer nicht authentifizierten externen Identität, bis der Nachweis steht. Der Bot löst ihn über einen Umkehrindex der Mitglieder des Arbeitsbereichs und ihrer verbundenen GitHub-Konten auf, neu aufgebaut nach einer TTL, weil sich Menschen anmelden und eingeladen werden, während der Server läuft.

Im Zweifel zu schließen sieht aus wie eine Leiter, und jede Sprosse antwortet in dem Thread, in dem sie abgelehnt hat:

  • Ein unbekannter Login — nicht verknüpft, oder verknüpft von jemandem, der kein Mitglied dieses Arbeitsbereichs ist — wird aufgefordert, sich anzumelden und zu prüfen, ob er dazugehört
  • Ein Nur-Lese-Mitglied (viewer oder guest) erfährt, dass seine Rolle keine Arbeit starten kann

Die beiden Fälle eines unbekannten Logins teilen sich eine Antwort: Der Umkehrindex liefert nur ein Mitglied dieses Arbeitsbereichs, ein nicht verknüpftes Konto und ein verknüpftes Nichtmitglied sind also derselbe Fehltreffer. Keiner davon kommt weiter. Ein Kommentar wird nie jemandem zugeschrieben, der ihn nicht geschrieben hat, und die Worte einer fremden Person gelangen nie in einen Arbeitsbereich, den sie nicht sehen kann.

Das Label ai-review hat keinen Autor zum Auflösen und steigt diese Leiter deshalb nicht hinauf. Es zu setzen startet das Review in dem Arbeitsbereich, der das Repository bereits verknüpft.

Jede Seite der Unterhaltung trägt eine andere Identität, und der Unterschied ist die Funktion:

  • Auf GitHub ist der Bot der Server. Jeder Kommentar, jede Reaktion und jede Antwort, die die Brücke schreibt, läuft über das Installationstoken der App. Niemand hat in einem Client etwas angeklickt, also leiht sich nichts das Konto einer Person — dieselbe Regel, die Webhooks und Polling von menschlichen Zugangsdaten fernhält.
  • Im Bereich gehört die Frage dir. Die Nachricht wird dem Mitglied zugeschrieben, zu dem der Autor aufgelöst wurde, und der Agentenlauf läuft in dessen Namen: Commits nennen es als Co-Autor, und der Autonomieregler des Bereichs sowie die Schutzregeln für Aktionen gelten genauso wie bei einer Nachricht, die in der App getippt wurde. Schreibvorgänge an die Forge aus dem Lauf gehen weiterhin als die App hinaus — dieselbe Regel wie im Punkt oben — und nicht über das persönliche Token des Mitglieds.

Review-Befunde auf GitHub zu veröffentlichen bleibt die Entscheidung einer Person, getroffen in Control Center. Eine Erwähnung kann ein Review starten; veröffentlicht wird es nur von einem Menschen.

Alles, was ein Bot-Konto verfasst, wird verworfen, bevor irgendein Tor läuft — unseres ausdrücklich, und jedes Suffix [bot], damit auch der Review-Bot einer anderen App unseren nicht weckt. Ohne das kämen die eigenen Antworten des Bots als neue Kommentare an und lösten ihn endlos erneut aus.

Das Suffix [bot] ist auch der Grund für die Kurzform. GitHub legt den Login eines App-Kontos auf <slug>[bot] fest, bietet dafür keine Autovervollständigung und löst @slug nie zur App auf — den bloßen Slug anzunehmen ist also die Entscheidung unseres Abgleichs, und ihn zu entdecken braucht eine rohe Suchspur über den Kommentar-Text, nicht den Erwähnungsindex von GitHub. Der Preis wird genannt, nicht geglättet: Ein Mensch, der denselben Slug trägt wie die App, spricht den Bot mit jeder Erwähnung seiner selbst in der Kurzform an. Unverwechselbare App-Namen machen die Kollision hypothetisch.

  • Kein automatisches Veröffentlichen. Befunde landen im Review-Bereich; das Veröffentlichen auf GitHub ist eine eigene Handlung eines Menschen
  • Keine unscharfe Identität. Der Autor löst auf genau ein Mitglied auf oder wird abgelehnt — eine Zuschreibung nach bestem Ermessen gibt es nicht
  • Kein Webhook der GitHub App. Diese Oberfläche registriert nie einen, es gibt also keine eingehende URL, die für PR-Kommentare offenzulegen wäre. Andere Webhooks des Produkts (Pipelines, Ticket-Sync) sind eine eigene, optionale Einrichtung.