- Bei der Nutzung der GitHub-API trat in einer Funktion zum Erzeugen von PR-Kommentar-Links ein Problem auf: Wegen eines ID-Mismatches funktionierten die Links nicht.
- Die Untersuchung ergab, dass GitHub zwei ID-Systeme parallel verwendet: die node ID von GraphQL und die database ID der REST API.
- Durch Base64-Decodierung der node ID wurde bestätigt, dass die unteren 32 Bit die database ID enthalten, sodass eine Umwandlung per einfacher Bitmasken-Operation möglich ist.
- Eine weitergehende Analyse zeigte, dass GitHub ein neues ID-Format auf MessagePack-Basis und ein stringbasiertes Legacy-Format gemischt verwendet.
- Diese Struktur zeigt die Doppelheit des internen Objekt-Identifikationssystems von GitHub und macht deutlich, dass Entwickler bei der API-Integration vorsichtig sein müssen.
Entdeckung des doppelten ID-Systems von GitHub
- Während der Entwicklung einer Funktion des AI-Code-Review-Tools von Greptile trat ein Problem auf, bei dem GitHub-PR-Kommentar-Links nicht funktionierten.
- Die gespeicherte Kommentar-ID wurde an die URL angehängt, doch beim Klicken führte sie nicht zur GitHub-Seite.
- Ein Blick in die GitHub-Dokumentation zeigte, dass die node ID der GraphQL API und die database ID der REST API als unterschiedliche Systeme existieren.
- Beispiel für eine node ID:
PRRC_kwDOL4aMSs6Tkzl8
- Beispiel für eine database ID:
2475899260
- Die node ID ist ein Base64-codierter String zur globalen Identifizierung von Objekten auf GitHub, während die database ID als ganzzahliger URL-Bezeichner verwendet wird.
Analyse der Beziehung zwischen node ID und database ID
- Durch den Vergleich der node IDs und database IDs mehrerer PR-Kommentare wurde bestätigt, dass beide Werte in konstanten Abständen ansteigen.
- Nach dem Decodieren des Base64-Teils der node ID entstand eine 96-Bit-Ganzzahl, deren untere 32 Bit mit der database ID übereinstimmten.
- Beispiel:
PRRC_kwDOL4aMSs6Tkzl8 → untere 32 Bit = 2475899260
- Die database ID lässt sich mit einer einfachen Bitmasken-Operation extrahieren.
- Die Umwandlung erfolgt mit einer Operation der Form
decoded & ((1 << 32) - 1).
GitHubs Legacy-ID-Format
- Beim Decodieren der node ID eines älteren Repositorys (
torvalds/linux) erschien ein String in einem anderen Format.
- Beispiel:
MDEwOlJlcG9zaXRvcnkyMzI1Mjk4 → 010:Repository2325298
- Dieses Format hat die Struktur
[Objekttyp-Nummer]:[Objektname][Database ID] und ist damit ein expliziter stringbasierter Bezeichner.
- Bei Tree-Objekten hat es die Form
04:Tree2325298:7201bfb9... und enthält zusätzlich die Repository-ID und den SHA-Wert.
- GitHub verwendet Legacy-Format und neues Format parallel, wobei das Format je nach Objekttyp und Erstellungszeitpunkt unterschiedlich ist.
Die Struktur des neuen node-ID-Formats
- Der GraphQL-Migrationsleitfaden von GitHub weist darauf hin, node IDs als opake Strings zu behandeln, dennoch existiert eine interne Struktur.
- Nach Base64-Decodierung und Entpacken mit MessagePack erscheint die Datenstruktur als Array.
- Beispiel:
[0, 47954445, 2475899260]
- Aufbau des Arrays
- Erstes Element (0): vermutlich ein Versionskennzeichen
- Zweites Element (47954445): die database ID des Repositorys
- Drittes Element (2475899260): die database ID des Objekts
- Je nach Objekttyp ist die Array-Länge unterschiedlich; Commits enthalten den SHA-Wert, Repositorys enthalten nur zwei Elemente.
Praktische Nutzung und Fazit
Noch keine Kommentare.