Workbooks mit git verwalten
Der Inhalt eines Workbooks lässt sich als Dateien in das eigene Repository ziehen, dort mit git durch Diff, Review und Pull Request führen und direkt zurückschreiben. Auch Transforms, die der Chat-Agent geschrieben hat, erscheinen am selben Ort — die Arbeitsweise „von der KI geschriebenes SQL erst reviewen, dann festschreiben“ ergibt sich damit von selbst.
d2b pull --workbook WB # → transforms/ sheets/ charts/ + d2b.jsond2b pull --data customers # also track a small base table as data/customers.csv (export = branch)git add -A && git commit -m "pull from D2B"# ... edit transforms/*.sql|py, sheets/*.json, data/*.csvd2b push --dry-run # what would be sent (only files that changed)d2b push --commit "$(git rev-parse --short HEAD)" # apply the changes → pin the git sha as a named versiongit commit -am "d2b push" # push updates d2b.json (sync hashes) — commit it too| Verzeichnis | Inhalt | pull | push |
|---|---|---|---|
transforms/ | SQL- / Python-Transforms (hierarchisch möglich, z. B. agg/monthly.sql) | ✅ | ✅ Nur geänderte werden per POST /transforms erneut ausgeführt (zählt als Datenoperation). In Abhängigkeitsreihenfolge (upstream zuerst) |
sheets/ | Darstellungs-Sheets {"blocks": [...]} | ✅ | ✅ PUT /sheets/{name} |
charts/ | Chart-config + recipe (das Tool und die Parameter der Erzeugung) | ✅ | ❌ Read-only — Charts werden aus dem recipe neu erzeugt; eine von Hand geänderte config lässt sich nicht neu erzeugen. Für Historie und Sichtprüfung |
data/ | CSVs der per --data opt-in aufgenommenen base-Tabellen (mit __d2b_row_id) | ✅ export = branch | ✅ Serverseitiger 3-way merge auf Zellebene mit Zeilen-ID als Schlüssel. Auf beiden Seiten geänderte Zellen landen in der Conflict-Queue des Workbooks (der D2B-Wert bleibt stehen) |
--data gilt nur für Basistabellen (deren Zeilen ihre eigene Wahrheitsquelle sind). Die strukturierte Ausgabe von mode=auto ist abgeleitet (Transform-Output) und kann nicht gebrancht werden — um Zeilen einer Tabelle über git zu führen, per --mode staged ingestieren, Parse-Spec prüfen und materialisieren (ergibt eine Basistabelle), oder sie über die Zeilen-API anlegen.
d2b.json ist das Manifest. Ein Transform-Eintrag ist {name, artifact_name, args, layer, hash} (für einen neuen Transform die Datei plus diesen Eintrag anlegen). hash ist der Digest zum Zeitpunkt der letzten Synchronisation (= Merge-Basis) und wird von der CLI gepflegt — d2b.json nach dem push committen.
Beim handschriftlichen Anlegen eines neuen Eintrags hash weglassen (weglassen — oder null — ist gleichwertig): der erste Push vergibt ihn und schreibt ihn zurück.
{ "workbook_id": "…", "transforms": { "agg/monthly.sql": { "name": "agg/monthly", "artifact_name": "product_sales", "args": {"src": "sales"}, "layer": null, "hash": "…" } }, "sheets": {"summary.json": {"name": "summary", "hash": "…"}}, "charts": {"trend.json": {"name": "trend", "readonly": true, "hash": "…"}}, "data": {"customers.csv": {"table": "customers", "branch_id": "…", "hash": "…"}}}Einen ganzen Workspace synchronisieren
Abschnitt betitelt „Einen ganzen Workspace synchronisieren“Hunderte oder Tausende Workbooks werden als ein Repository = ein Workspace behandelt. Die d2b.json im Wurzelverzeichnis (das Verzeichnisbuch) legt den Workspace fest, und jedes Workbook landet in workbooks/<Titel>--<erste 8 Zeichen seiner id>/ mit dem Layout von oben, eigene d2b.json inklusive.
d2b pull --workspace WS # beim ersten Mal: schreibt das Verzeichnisbuch und holt jedes Workbook des Workspace (parallel, --jobs N)d2b pull # danach: aus dem Verzeichnisbuch; ein neues Workbook erscheint von selbstd2b pull --prune # entfernt die Verzeichnisse von Workbooks, die den Workspace verlassen haben (sichtbar im Diff)d2b status --strict # exit 2, wenn Verzeichnisbuch, Verzeichnisse und Server nicht übereinstimmen (als Pflichtprüfung in CI)d2b push --commit "$(git rev-parse --short HEAD)" # nur geänderte Workbooks werden gesendet- Die Zugehörigkeit ist eine Tatsache des Servers:
pulllistet jedes Workbook des Workspace auf und schreibt nie ein Verzeichnis, das das Verzeichnisbuch nicht kennt. Ein anderer Workspace lässt sich nicht in dasselbe Repository holen – es gibt keinen Schalter dafür. - Das Verzeichnis eines Workbooks wird beim ersten Pull festgelegt; eine Umbenennung verschiebt es nicht. Seine id steht im Verzeichnisnamen und in der ersten Zeile jeder Transformationsdatei,
-- d2b ws=… wb=… transform=…(diese Zeile geht nie an den Server und zählt nie als Änderung). pushsendet gar nichts, wenn es ein dem Verzeichnisbuch unbekanntes Verzeichnis, eine Datei mit dem Header eines anderen Workbooks oder ein an eine andereworkbook_idgebundenes Manifest findet.- Geben Sie CI ein an den Workspace gepinntes PAT (
workspace_idbeiPOST /api/control/account/keysoderresource: "workspace:<id>"beiPOST /api/v1/me/tokens): Selbst bei falscher Konfiguration antwortet der Server für jeden anderen Workspace mit 403. Die Anmeldung ausd2b loginreicht über das ganze Konto und ist nicht der richtige Schlüssel für CI. data/(Zeilen) bleibt ein Opt-in je Workbook (d2b pull --data TABLEinnerhalb vonworkbooks/<dir>/).
Ein Verzeichnis ohne Verzeichnisbuch behält das oben beschriebene Verhalten für ein einzelnes Workbook.
Konfliktregeln
Abschnitt betitelt „Konfliktregeln“- Textartefakte (transforms / sheets / charts) werden nie stillschweigend überschrieben (derselbe Vertrag wie das optimistische Locking der Zeilen-API): Haben sich seit der letzten Synchronisation beide Seiten geändert, lehnen pull wie push ab und geben die betroffenen Dateien als JSON zurück. Die Richtung von
--forcehängt vom Befehl ab: push--forcesetzt die lokale Seite durch; pull--forceübernimmt die Server-Seite (lokale Änderungen gehen verloren) data/verhält sich anders: Gleichzeitige Änderungen werden nicht abgelehnt, der serverseitige 3-way merge entscheidet auf Zellebene. Nach dem push wird das CSV aus dem Merge-Ergebnis neu geholt und ein neuer branch eröffnet (auch Änderungen der D2B-Seite landen so lokal). Abgeleitete Tabellen lassen sich nicht branchen (400). Merge-Limit 100.000 Zeilen — gedacht für kleine Tabellen wie Stammdaten oder Zuordnungstabellen- Lokal gelöschte Dateien löschen nichts auf dem Server (nur ein Bericht unter
deleted_locally).--prunelöscht Output-Tabellen von Transforms und Sheets (das Löschen von Output-Tabellen erfordertworkbooks:delete). Beidata/endet nur das Tracking, die Tabelle bleibt bestehen - Schlüssel in
d2b.jsonmüssen normalisierte relative Pfade innerhalb ihres eigenen Section-Verzeichnisses sein: absolute Pfade,.., Windows-Laufwerke und nicht normalisierte Pfade werden bei pull wie push abgelehnt. Eine synchronisierte Datei, die ein symbolischer Link ist (transforms/*.sql|pyund dergleichen), wird ebenfalls abgelehnt — über einen Link wird nichts gelesen oder geschrieben (ein Link auf eine Datei, die die Section nie liest, wird einfach ignoriert)
Den Roundtrip mit GitHub Actions automatisieren
Abschnitt betitelt „Den Roundtrip mit GitHub Actions automatisieren“Weder eine GitHub App noch eine Integrationskonfiguration auf D2B-Seite ist nötig — der Roundtrip zwischen Repository und Workbook schließt sich allein über die CLI.
d2b github-workflow > .github/workflows/d2b.yml# Secrets: D2B_API_KEY (a workbooks:write PAT). Variables: D2B_BASE_URL- Merge nach
main(mit Änderungen an synchronisierten Dateien) →d2b push --commit <sha>→ das aktualisierted2b.jsonwird automatisch committet - Zeitgesteuert (Standard: stündlich) und manuell →
d2b pull→ bei Differenzen ein Pull Request (Branchd2b/pull). So reviewen Menschen, was der Agent auf Workbook-Seite geändert hat, und mergen es
Im SDK sind client.transforms.list(wb) / client.sheets.list(wb) / client.charts.list(wb) / client.export.branch(wb, [table]) / client.tables.merge(...) dieselbe Oberfläche.