Demandes de modification
Comment le travail d’une session rejoint la branche par défaut après révision.
Une demande de modification (CR) fusionne une branche Git dans une autre. Beeuni crée une CR à partir de la branche d’une session (head_ref) vers la branche par défaut du projet (base_ref, généralement main). La ligne de la CR contient des métadonnées ; la fusion, le diff et les vérifications de conflits sont effectués par de véritables opérations Git sur le dépôt du projet. Une CR est le seul moyen pour que le travail d’une session rejoigne la branche par défaut.
Pourquoi passer par une CR
Une session s’exécute dans un environnement isolé sur sa propre branche, nommée d’après l’ID de la session. L’environnement isolé n’est pas permanent, mais la branche, elle, le reste : Git est le seul enregistrement durable du travail d’une session. Chaque nouvelle session démarre depuis la branche par défaut. Tant qu’une CR n’est pas fusionnée, le travail reste sur sa propre branche, sans révision et invisible pour tous les autres agents, déclencheurs et collaborateurs. Cela s’applique à toutes les modifications : code, agents, compétences et manifeste (beeuni.yaml) — sans exception.
Règle imposée aux agents
Un agent doit ouvrir une CR pour intégrer toute modification à la branche par défaut du projet. L’agent ne fusionne pas sa propre CR : la fusion relève de la décision de l’utilisateur. Respectez les étapes suivantes :
- Valider les modifications sur la branche de la session (
$BEEUNI_BRANCH_NAME). Faites de petits commits fonctionnels. Ne réécrivez pas l’historique et ne faites pas de push forcé. - Poussez la branche :
git push origin HEAD. - Ouvrez la CR :
beeuni cr open --title "..." --description "...". Dans un environnement isolé de session,--headet--sessionprennent par défaut les valeurs$BEEUNI_BRANCH_NAMEet$BEEUNI_SESSION_ID.--baseprend par défaut la valeur de la branche par défaut du projet. - Indiquez le numéro de la CR à l’utilisateur afin qu’il puisse la réviser.
- Arrêtez-vous. Ne fusionnez pas vous-même la CR.
Anti-modèles
- Forcer un push vers la branche par défaut. Cela rompt le processus de révision, même si le système le permet.
- « C’est sur ma branche, récupérez-la vous-même. » La branche de session disparaît à l’arrêt de l’environnement isolé, à moins qu’une CR ne l’ait fusionnée entre-temps.
- Envoyer la modification sous forme de fichier, de texte collé ou d’archive. Le système de CR règle déjà ce problème.
Modèle de données
Les CR sont stockées dans la table change_requests.
| Colonne | Type | Remarques |
|---|---|---|
cr_id |
uuid | Clé primaire. Identifiant de l’API REST. |
project_id |
uuid | Projet auquel appartient la CR. |
number |
integer | Numéro d’affichage propre au projet (#1, #2…). Unique par projet. N’est jamais réutilisé. |
title |
text | Obligatoire. |
description |
text | Valeur par défaut : chaîne vide. |
base_ref |
text | Branche dans laquelle la fusion est effectuée. Généralement main. |
head_ref |
text | Branche depuis laquelle la fusion est effectuée. Dans une session, il s’agit de l’ID de la session (un UUID). |
status |
enum | open, merged ou closed. |
head_commit_sha |
text | Actualisé à partir de la tête en direct de head_ref à chaque lecture pour les CR ouvertes. Enregistré au moment de la fusion pour les CR fusionnées. |
base_commit_sha |
text | Même règle pour base_ref. |
origin_session_id |
text | Session qui a ouvert la CR. Défini sur null si cette session est supprimée. |
created_by |
uuid | Utilisateur qui a créé la CR. |
merged_at / merged_by |
timestamp / uuid | Date et auteur de la fusion de la CR. |
merge_commit_sha |
text | Commit de fusion. Égal à head_commit_sha en cas d’avance rapide. |
closed_at / closed_by |
timestamp / uuid | Date et auteur de la fermeture de la CR sans fusion. |
metadata |
jsonb | Contient requested_changes, une liste d’entrées {text, by, at} ajoutées par POST /:crId/request-changes. Les CR n’ont pas de table de commentaires distincte. |
created_at / updated_at |
timestamp | Défini à la création. Mis à jour à chaque changement d’état ou actualisation de SHA. |
Un index unique sur (project_id, number) permet de référencer une CR par son numéro court plutôt que par son UUID.
Cycle de vie
open ──(merge)──▶ merged (terminal)
open ──(close)──▶ closed ──(reopen)──▶ open
openest l’état initial.closedest réversible.POST /:crId/reopenle rétablit àopen.mergedest un état terminal. Vous ne pouvez ni rouvrir ni fermer une CR fusionnée. Ouvrez plutôt une nouvelle CR à partir de l’état fusionné.
Beeuni refuse de créer une CR si sa branche n’a aucun commit en avance sur la branche par défaut. Cela signifie généralement que l’agent a effectué des commits localement, mais ne les a jamais poussés. Poussez les commits, puis créez à nouveau la CR.
Actualisation des SHA
Pour une CR ouverte, Beeuni actualise head_commit_sha et base_commit_sha à partir des branches en direct à chaque GET. Si le dépôt est inaccessible ou qu’une branche est introuvable, Beeuni ignore l’actualisation et renvoie les dernières métadonnées connues de la CR. Une CR fusionnée conserve les SHA enregistrés au moment de la fusion : Beeuni ne les actualise plus.
Mécanique de fusion
POST /v1/projects/:projectId/change-requests/:crId/merge exécute les étapes suivantes.
- Beeuni lit le manifeste (
beeuni.yaml) depuishead_refet le valide selon le schéma du manifeste. Une branche sans manifeste est acceptée. Un manifeste invalide renvoie422aveccode: "MANIFEST_INVALID"et interrompt la fusion. - Beeuni effectue une avance rapide de
base_refsihead_refest strictement en avance sur cette branche. - Sinon, Beeuni crée un commit de fusion. Le message par défaut est
Merge CR #<n>: <title>, mais vous pouvez le remplacer avecmessagedans le corps de la requête. L’auteur du commit estBeeuni <noreply@beeuni.com>. - En cas de conflit, la réponse
409contient la liste des conflits. Vérifiez cette même liste avecGET /:crId/merge-previewavant la fusion. - En cas de réussite, Beeuni définit
statussurmerged, enregistremerged_at,merged_byetmerge_commit_sha, puis invalide le cache Git du projet.
La fusion d’une CR dont l’état n’est pas open renvoie 409.
Aperçu de la fusion
GET /:crId/merge-preview renvoie :
| Champ | Type | Signification |
|---|---|---|
base_sha |
string | Tête actuelle de base_ref. |
head_sha |
string | Tête actuelle de head_ref. |
merge_base |
string | null | Ancêtre commun. Null si les historiques ne sont pas apparentés. |
is_up_to_date |
boolean | head_ref est entièrement fusionnée dans base_ref. |
can_merge |
boolean | Aucun conflit. |
can_fast_forward |
boolean | head_ref est strictement en avance sur base_ref. |
conflicts |
string[] | Chemins des fichiers susceptibles d’entrer en conflit. |
API REST
Toutes les routes se trouvent sous /v1/projects/:projectId/change-requests.
| Méthode | Chemin | Remarques |
|---|---|---|
| GET | / |
?status=open|merged|closed|all. Sans filtre, renvoie tous les états. |
| POST | / |
Corps : {title, description?, head_ref, base_ref?, session_id?}. Renvoie 201. |
| GET | /:crId |
Renvoie la CR. Actualise les SHA à titre d’effet secondaire. |
| PATCH | /:crId |
Modifie title ou description. 409 si la CR n’est pas open. |
| GET | /:crId/diff |
Patch unifié : liste de fichiers, ajouts et suppressions. |
| GET | /:crId/merge-preview |
Voir « Aperçu de la fusion » ci-dessus. |
| POST | /:crId/merge |
Corps : {message?}. 422 si le manifeste est invalide. 409 en cas de conflit ou si la CR n’est pas open. |
| POST | /:crId/close |
409 si la CR est déjà merged. |
| POST | /:crId/reopen |
409 si la CR n’est pas closed. |
| POST | /:crId/request-changes |
Corps : {feedback}. Ajoute à metadata.requested_changes et réveille l’agent de la session d’origine. 409 si la CR n’est pas open. |
POST / rejette une head_ref qui n’a aucun commit en avance sur base_ref : 422 code: "CR_HEAD_NOT_AHEAD". C’est l’erreur qu’un agent reçoit s’il ouvre une CR avant d’avoir poussé sa branche.
Autorisation
Les routes de lecture nécessitent un accès en lecture au projet. Les routes d’écriture nécessitent un accès en écriture. Chaque action d’écriture requiert également une capacité, indiquée ci-dessous pour un jeton complet et pour le jeton à portée limitée d’une session.
| Action | Capacité |
|---|---|
| Ouvrir une CR | project.gitops.push |
| Demander des modifications | project.review.act |
| Fusionner | project.gitops.merge |
Une capacité par action, pour un jeton complet comme pour le jeton à portée limitée d’une session. L’ouverture et la fusion sont des permissions distinctes : un jeton peut donc ouvrir des demandes de modification sans pouvoir les fusionner — c’est le mécanisme qui permet d’appliquer la règle imposée aux agents décrite ci-dessus.
project.cr.open et project.cr.merge étaient les anciens noms de project.gitops.push et project.gitops.merge avant la migration : il s’agissait de la même capacité sous un autre nom. Un beeuni.yaml qui en répertorie toujours une reste fonctionnel (l’autorisation est convertie en nom actuel lors de sa résolution), mais utilisez le nom gitops dans toute nouvelle configuration.
Une session ne peut jamais fusionner une demande de modification qu’elle a elle-même ouverte, quelles que soient les autorisations qui lui ont été accordées. Cette règle est structurelle et ne dépend pas des capacités.