Änderungsanfragen
So gelangt die Arbeit an einer Session nach der Überprüfung in den Standard-Branch.
Eine Änderungsanfrage (CR) führt einen Git-Branch mit einem anderen zusammen. Beeuni erstellt eine CR vom Branch einer Sitzung (head_ref) zum Standardbranch des Projekts (base_ref, normalerweise main). Der CR-Eintrag enthält Metadaten; Zusammenführung, Diff und Konfliktprüfungen erfolgen als echte Git-Operationen im Repository des Projekts. Eine CR ist der einzige Weg, wie Sitzungsarbeit in den Standardbranch gelangt.
Warum die Arbeit über eine CR läuft
Eine Sitzung läuft in einer Sandbox auf einem eigenen Branch, der nach der Sitzungs-ID benannt ist. Die Sandbox besteht nicht ewig, der Branch aber schon: Git ist der einzige dauerhafte Datensatz der Arbeit einer Sitzung. Jede neue Sitzung beginnt beim Standardbranch. Bis eine CR zusammengeführt wird, bleibt die Arbeit auf ihrem eigenen Branch, ungeprüft und für alle anderen Agenten, Trigger und Mitwirkenden unsichtbar. Das gilt für jede Änderung: Code, Agenten, Skills und das Manifest (beeuni.yaml) — ohne Ausnahme.
Vorgaben für Agenten
Ein Agent muss eine CR eröffnen, um Änderungen in den Standardbranch des Projekts zu übernehmen. Der Agent führt seine eigene CR nicht zusammen — die Zusammenführung ist Sache des Benutzers. Halte dich an diese Vorgaben:
- Committe auf dem Sitzungsbranch (
$BEEUNI_BRANCH_NAME). Erstelle kleine, funktionierende Commits. Schreibe den Verlauf nicht um und erzwinge keinen Push. - Pushe den Branch:
git push origin HEAD. - Eröffne die CR:
beeuni cr open --title "..." --description "...". In einer Sitzungs-Sandbox haben--headund--sessionstandardmäßig den Wert$BEEUNI_BRANCH_NAMEund$BEEUNI_SESSION_ID.--baseist standardmäßig der Standardbranch des Projekts. - Teile dem Benutzer die CR-Nummer mit, damit er sie überprüfen kann.
- Halte an. Führe die CR nicht selbst zusammen.
Antimuster
- Force-Push auf den Standardbranch. Das verletzt die Review-Vereinbarung, selbst wenn das Backend es zulässt.
- „Der Branch ist da, hol ihn dir selbst.“ Sobald die Sandbox beendet wird, ist der Sitzungsbranch weg, sofern er nicht vorher durch eine CR zusammengeführt wurde.
- Die Änderung als Datei, eingefügten Text oder Archiv senden. Das CR-System löst dieses Problem bereits.
Datenmodell
CRs befinden sich in der Tabelle change_requests.
| Spalte | Typ | Hinweise |
|---|---|---|
cr_id |
uuid | Primärschlüssel. Die Kennung der REST-API. |
project_id |
uuid | Das Projekt, zu dem die CR gehört. |
number |
integer | Anzeigenummer pro Projekt (#1, #2…). Innerhalb eines Projekts eindeutig. Wird nie wiederverwendet. |
title |
text | Erforderlich. |
description |
text | Standardmäßig eine leere Zeichenfolge. |
base_ref |
text | Der Branch, in den zusammengeführt wird. Normalerweise main. |
head_ref |
text | Der Branch, aus dem zusammengeführt wird. In einer Sitzung ist dies die Sitzungs-ID (eine UUID). |
status |
enum | open, merged oder closed. |
head_commit_sha |
text | Bei offenen CRs bei jedem Lesezugriff mit dem aktuellen head_ref-Tip aktualisiert. Bei zusammengeführten CRs zum Zeitpunkt der Zusammenführung erfasst. |
base_commit_sha |
text | Gleiche Regel, für base_ref. |
origin_session_id |
text | Die Sitzung, die die CR eröffnet hat. Wird auf null gesetzt, wenn diese Sitzung gelöscht wird. |
created_by |
uuid | Der Benutzer, der die CR erstellt hat. |
merged_at / merged_by |
timestamp / uuid | Wann und von wem die CR zusammengeführt wurde. |
merge_commit_sha |
text | Der Merge-Commit. Bei einem Fast-Forward entspricht er head_commit_sha. |
closed_at / closed_by |
timestamp / uuid | Wann und von wem die CR ohne Zusammenführung geschlossen wurde. |
metadata |
jsonb | Enthält requested_changes, eine Liste von {text, by, at}-Einträgen, die von POST /:crId/request-changes hinzugefügt wurden. CRs haben keine separate Kommentartabelle. |
created_at / updated_at |
timestamp | Wird bei der Erstellung gesetzt. Bei jeder Statusänderung oder SHA-Aktualisierung aktualisiert. |
Ein eindeutiger Index auf (project_id, number) ermöglicht es, eine CR über ihre Kurznummer statt über ihre UUID zu referenzieren.
Lebenszyklus
open ──(merge)──▶ merged (terminal)
open ──(close)──▶ closed ──(reopen)──▶ open
openist der Anfangsstatus.closedist umkehrbar.POST /:crId/reopensetzt den Status aufopenzurück.mergedist endgültig. Eine zusammengeführte CR kann nicht wieder geöffnet oder geschlossen werden. Eröffne stattdessen eine neue CR auf Basis des zusammengeführten Zustands.
Beeuni lehnt die Erstellung einer CR ab, wenn der Branch keine Commits enthält, die dem Standardbranch voraus sind. Das bedeutet meist, dass der Agent lokal committet, aber nie gepusht hat. Pushe die Commits und erstelle die CR erneut.
SHA-Aktualisierung
Bei einer offenen CR aktualisiert Beeuni head_commit_sha und base_commit_sha bei jedem GET anhand der aktuellen Branches. Ist das Repository nicht erreichbar oder fehlt ein Branch, überspringt Beeuni die Aktualisierung und liefert die zuletzt bekannten Metadaten der CR. Bei einer zusammengeführten CR bleiben die zum Zeitpunkt der Zusammenführung erfassten SHAs erhalten — Beeuni aktualisiert sie danach nie wieder.
Zusammenführungsablauf
POST /v1/projects/:projectId/change-requests/:crId/merge führt die folgenden Schritte aus.
- Beeuni liest das Manifest (
beeuni.yaml) aushead_refund validiert es anhand des Manifest-Schemas. Ein Branch ohne Manifest wird akzeptiert. Bei einem ungültigen Manifest wird422mitcode: "MANIFEST_INVALID"zurückgegeben und die Zusammenführung abgebrochen. - Beeuni führt einen Fast-Forward von
base_refdurch, wennhead_refihm strikt voraus ist. - Andernfalls erstellt Beeuni einen Merge-Commit. Die Standardnachricht lautet
Merge CR #<n>: <title>und kann mitmessageim Anfrage-Body überschrieben werden. Autor des Commits istBeeuni <noreply@beeuni.com>. - Bei einem Konflikt wird
409mit der Konfliktliste zurückgegeben. Prüfe dieselbe Liste vor der Zusammenführung mitGET /:crId/merge-preview. - Bei Erfolg setzt Beeuni
statusaufmerged, erfasstmerged_at,merged_byundmerge_commit_shaund invalidiert den Git-Cache des Projekts.
Der Versuch, eine CR zusammenzuführen, die nicht open ist, führt zu 409.
Vorschau der Zusammenführung
GET /:crId/merge-preview gibt Folgendes zurück:
| Feld | Typ | Bedeutung |
|---|---|---|
base_sha |
string | Aktueller Tip von base_ref. |
head_sha |
string | Aktueller Tip von head_ref. |
merge_base |
string | null | Gemeinsamer Vorfahr. Null, wenn die Verläufe nicht zusammenhängen. |
is_up_to_date |
boolean | head_ref ist vollständig in base_ref zusammengeführt. |
can_merge |
boolean | Keine Konflikte. |
can_fast_forward |
boolean | head_ref ist base_ref strikt voraus. |
conflicts |
string[] | Dateipfade, bei denen Konflikte auftreten würden. |
REST-API
Alle Routen befinden sich unter /v1/projects/:projectId/change-requests.
| Methode | Pfad | Hinweise |
|---|---|---|
| GET | / |
?status=open|merged|closed|all. Ohne Filter werden alle Status zurückgegeben. |
| POST | / |
Body: {title, description?, head_ref, base_ref?, session_id?}. Gibt 201 zurück. |
| GET | /:crId |
Gibt die CR zurück. Aktualisiert dabei auch die SHAs. |
| PATCH | /:crId |
Bearbeitet title oder description. 409, wenn nicht open. |
| GET | /:crId/diff |
Vereinheitlichter Patch: Dateiliste, Ergänzungen und Löschungen. |
| GET | /:crId/merge-preview |
Siehe „Vorschau der Zusammenführung“ oben. |
| POST | /:crId/merge |
Body: {message?}. 422 bei einem ungültigen Manifest. 409 bei Konflikten oder wenn nicht open. |
| POST | /:crId/close |
409, wenn bereits merged. |
| POST | /:crId/reopen |
409, wenn nicht closed. |
| POST | /:crId/request-changes |
Body: {feedback}. Fügt den Eintrag an metadata.requested_changes an und weckt den Agenten der ursprünglichen Sitzung. 409, wenn nicht open. |
POST / lehnt eine head_ref ab, deren Branch keine Commits enthält, die base_ref voraus sind: 422 code: "CR_HEAD_NOT_AHEAD". Diesen Fehler sieht ein Agent, wenn er eine CR eröffnet, bevor er seinen Branch pusht.
Autorisierung
Für Lesezugriffe ist Lesezugriff auf das Projekt erforderlich. Für Schreibzugriffe ist Schreibzugriff erforderlich. Jede Schreibaktion benötigt außerdem eine Berechtigung, die unten sowohl für ein vollständiges Token als auch für das eingeschränkte Token einer Sitzung angegeben ist.
| Aktion | Berechtigung |
|---|---|
| CR eröffnen | project.gitops.push |
| Änderungen anfordern | project.review.act |
| Zusammenführen | project.gitops.merge |
Für jede Aktion ist eine eigene Berechtigung erforderlich, sowohl bei vollständigen Tokens als auch bei eingeschränkten Sitzungstokens. Das Eröffnen und Zusammenführen sind getrennte Berechtigungen. Ein Token kann also Änderungsanfragen eröffnen, ohne sie zusammenführen zu dürfen — so wird die oben beschriebene Vorgabe für Agenten umgesetzt.
project.cr.open und project.cr.merge waren vor der Umstellung die Namen von project.gitops.push und project.gitops.merge — dieselbe Berechtigung unter einem zweiten Namen. Ein beeuni.yaml, das noch einen dieser Namen aufführt, funktioniert weiterhin (beim Auflösen wird die Berechtigung auf die aktuelle Schreibweise umgeschrieben). Verwende für neue Einträge jedoch den gitops-Namen.
Eine Sitzung kann niemals eine Änderungsanfrage zusammenführen, die sie selbst eröffnet hat, ungeachtet der erteilten Berechtigungen. Diese Regel ist strukturell und keine Berechtigung.