Integration GitHub
Comment BernOps se connecte aux repositories GitHub, quelles permissions sont requises et comment les exports restent revus.
Sur cette page
La connexion GitHub relie un projet BernOps a un repository disponible via une installation GitHub App. L'implementation actuelle utilise ce lien pour lister les repositories disponibles, inspecter l'arborescence du repository et exporter les jobs Playwright geres par BernOps sous forme de pull requests en brouillon.
BernOps connecte un seul repository par projet. BernOps ne clone pas le repository, n'execute pas le code du repository, ne merge pas les pull requests, ne modifie pas les parametres du repository, ne gere pas les secrets GitHub et n'ecrit pas directement sur la branche par defaut.
Ce que fait l'integration
Apres connexion d'un projet, BernOps peut effectuer ces actions GitHub via la GitHub App installee :
- Lister les repositories exposes par l'installation pour qu'un admin projet puisse en choisir un.
- Stocker dans BernOps l'identite du repository choisi, sa branche par defaut et le dossier d'export.
- Lire l'arborescence du repository selectionne quand le projet demande l'etat du repository.
- Lire les fichiers existants aux chemins d'export BernOps pour eviter d'ecraser des fichiers que BernOps ne possede pas.
- Creer une branche BernOps nommee comme
bernops/update-tests-20260503121000-ab12cd34. - Committer les fichiers de jobs Playwright geres par BernOps sur cette branche avec le message
Update BernOps tests. - Ouvrir ou mettre a jour une pull request en brouillon intitulee
Update BernOps tests. - Suivre l'etat de la pull request via les webhooks GitHub et mettre a jour les metadonnees de synchronisation des jobs BernOps.
BernOps exporte uniquement les jobs enregistres dont les metadonnees indiquent source_kind = bernops et managed_by = platform. L'endpoint d'export n'exporte pas de fichiers arbitraires du repository.
Flux de configuration
L'installation commence dans BernOps, pas directement depuis les parametres de la GitHub App. L'URL d'installation generee par BernOps transporte un etat signe qui lie le flux GitHub a un projet, un workspace, un utilisateur et un nonce BernOps.
- Un utilisateur BernOps connecte avec acces admin au projet appelle
POST /api/projects/{projectId}/github/install-url. - Le backend cree un nonce de configuration aleatoire, le stocke dans
github_setup_states, signe un payload d'etat avec HMAC-SHA256 et fixe une expiration de 10 minutes. - Le navigateur est redirige vers l'URL d'autorisation OAuth de la GitHub App avec cet etat signe.
- GitHub redirige vers
GET /api/github/setupavec uncodeOAuth. - Le backend echange le code contre un token utilisateur GitHub, chiffre ce token avec AES-GCM en utilisant une cle derivee du secret webhook GitHub, le stocke temporairement sur la ligne d'etat de configuration, puis redirige vers l'URL d'installation de la GitHub App avec le meme etat signe.
- GitHub redirige vers
GET /api/github/setupavec uninstallation_id. - Le backend verifie l'etat signe, charge la ligne d'etat non consommee, dechiffre le token utilisateur temporaire et appelle GitHub pour verifier que l'utilisateur GitHub ayant autorise le flux peut acceder a l'installation retournee.
- Le backend recupere les metadonnees d'installation depuis GitHub et finalise la configuration via une RPC base de donnees service-role qui consomme l'etat et upsert l'installation de maniere atomique.
- Le token utilisateur GitHub chiffre est efface lorsque la configuration est finalisee. Les lignes de configuration expirees ont aussi leur token temporaire efface par le worker de retention.
Si l'etat signe est manquant, expire, reutilise ou ne correspond pas au projet, workspace et utilisateur stockes, la configuration est rejetee et l'utilisateur est redirige vers une page de resultat de configuration GitHub.
Permissions GitHub requises
BernOps doit etre configure avec les permissions GitHub App minimales necessaires au code actuel. La documentation GitHub indique que les GitHub Apps commencent sans permission et que les permissions de l'app determinent les APIs et webhooks utilisables. GitHub recommande aussi de choisir les permissions minimales requises par l'app.
| Permission GitHub App | Acces | Pourquoi BernOps en a besoin |
|---|---|---|
| Metadata | Read-only | Identifier les installations et repositories exposes par l'installation. |
| Contents | Read and write | Lire les arbres et contenus du repository, puis creer des Git trees, commits et refs de branche pour les branches d'export BernOps. |
| Pull requests | Read and write | Ouvrir ou mettre a jour des pull requests en brouillon et traiter les changements d'etat de pull request. |
Aucune permission d'organisation GitHub n'est requise par l'integration actuelle. Le code actuel n'utilise pas les permissions GitHub Actions, Secrets, Administration, Deployments, Packages, Members, Issues, Checks ou Workflows.
GitHub permet d'accorder une installation d'app a tous les repositories ou seulement a des repositories selectionnes. Les actions BernOps cote projet sont stockees contre un seul repository choisi, mais le token d'installation GitHub est limite par ce que l'installation GitHub accorde. Pour le moindre privilege, selectionnez seulement les repositories que BernOps doit pouvoir lister et connecter.
Evenements webhook
La GitHub App doit souscrire a ces evenements :
InstallationInstallation repositoriesPull request
GitHub envoie automatiquement des livraisons ping quand les webhooks sont configures ou testes. BernOps accepte ping mais l'enregistre comme ignore.
Si BernOps ne peut pas traiter une livraison apres l'avoir enregistree, l'endpoint enregistre l'echec et retourne une reponse non-2xx afin que GitHub puisse retenter la livraison.
BernOps traite les evenements souscrits ainsi :
| Evenement | Actions traitees par BernOps |
|---|---|
installation | Supprime les installations locales quand GitHub supprime l'installation, et marque les installations comme suspendues ou non suspendues quand GitHub envoie ces actions. |
installation_repositories | Deconnecte les repositories BernOps quand un repository est retire de l'installation GitHub App. |
pull_request | Met a jour les pull requests d'export BernOps suivies, marque les jobs synced quand une PR suivie est mergee, et remet les metadonnees des jobs pending a not_synced quand une PR suivie est fermee sans merge. |
| Autres evenements | Ignores apres verification de signature et enregistrement de la livraison. |
Auth et gestion des tokens
GitHub documente trois modes d'authentification pour les GitHub Apps : authentifier l'app avec un JWT, authentifier une installation d'app avec un token d'installation, et authentifier au nom d'un utilisateur avec un token utilisateur. BernOps utilise les trois pour des usages differents.
| Token ou identifiant | Utilisation | Traitement par BernOps |
|---|---|---|
| Cle privee GitHub App | Backend uniquement | Chargee depuis GITHUB_APP_PRIVATE_KEY. Sert a signer des JWT d'app courts avec RS256. |
| JWT d'app | Backend vers GitHub | Sert a recuperer les metadonnees d'installation et a obtenir des tokens d'installation. |
| Token d'installation | Backend vers GitHub | Sert a lister les repositories, lire arbres/fichiers, ecrire Git trees/commits/refs, et creer ou mettre a jour des pull requests. Cache en memoire backend et rafraichi avant expiration. Non stocke en base. |
| Token OAuth utilisateur pendant la configuration | Backend vers GitHub | Sert uniquement a verifier que l'utilisateur GitHub installateur peut acceder a l'installation retournee. Chiffre temporairement dans github_setup_states, puis efface quand la configuration est finalisee. |
| Secret webhook | Backend uniquement | Charge depuis GITHUB_WEBHOOK_SECRET. Sert a verifier les signatures webhook GitHub et a signer l'etat de configuration. |
Si la configuration GitHub requise est manquante, les endpoints GitHub retournent 503 au lieu de continuer avec une integration partielle.
Donnees stockees par BernOps
BernOps stocke les metadonnees d'integration GitHub necessaires pour garder la connexion projet et l'etat d'export coherents.
| Donnee | Champs stockes |
|---|---|
| Installation | ID workspace, ID installation GitHub, login du compte, type de compte, mode de selection des repositories, JSON de permissions, installateur, timestamp de suspension, timestamps. |
| Connexion repository | ID projet, ID ligne d'installation, ID repository GitHub, nom complet, owner, nom, branche par defaut, dossier d'export, utilisateur connecteur, timestamps. |
| Pull request d'export | ID connexion repository, nom de branche, branche de base, SHA du commit head, numero de PR, URL de PR, statut, indicateur draft, derniere erreur, createur, timestamps. |
| Livraison webhook | ID livraison GitHub, type d'evenement, action, ID installation, ID repository, statut de traitement, derniere erreur, timestamps de reception/traitement. |
| Etat de configuration | Nonce, ID projet, ID workspace, ID utilisateur, expiration, timestamp de consommation, token de configuration chiffre temporaire, timestamp de fin OAuth. |
BernOps ne stocke pas les corps bruts des payloads webhook GitHub dans github_webhook_deliveries. BernOps stocke les metadonnees de livraison et le statut de traitement necessaires a la deduplication, aux retries et a l'audit.
Comportement d'export
Quand un admin projet exporte les tests vers GitHub, BernOps n'ecrit pas sur la branche par defaut. BernOps cree ou met a jour une branche BernOps et ouvre ou met a jour une pull request en brouillon.
Le pipeline d'export est :
- Charger le repository connecte et l'installation.
- Acquerir un verrou d'export au niveau du repository pendant au plus 30 minutes pour que deux requetes d'export ne puissent pas ecrire des branches GitHub concurrentes en meme temps.
- Charger les jobs geres par BernOps pour le projet.
- Construire les chemins cible en joignant le dossier d'export configure avec le nom de fichier de chaque job.
- Resoudre le SHA courant de la branche de base et lire les fichiers existants depuis ce commit exact pour detecter les conflits.
- Creer un Git tree, un commit et une ref de branche via les APIs GitHub Git, en echouant si la branche de base bouge apres la verification de conflits.
- Ouvrir une nouvelle pull request en brouillon ou mettre a jour la pull request BernOps ouverte et suivie.
- Rafraichir les metadonnees de fichiers depuis GitHub et marquer les jobs exportes comme
pending_pr.
Le dossier d'export par defaut est bernops/e2e. Un dossier personnalise est accepte seulement s'il est un chemin relatif sur. Les chemins absolus, backslashes, .. et chemins qui sortent du dossier du repository apres nettoyage sont rejetes.
Protection contre les conflits
BernOps ignore les fichiers au lieu d'ecraser du contenu repository qu'il ne peut pas prouver posseder.
| Situation | Resultat |
|---|---|
| Le fichier cible existe deja mais le job BernOps n'a pas de SHA de blob GitHub deja enregistre | Ignore avec remote file already exists and has not been exported by BernOps. |
| Le fichier cible a change dans GitHub depuis le dernier export BernOps | Ignore avec remote file changed since the last BernOps export. |
| Le fichier cible a ete supprime apres un export BernOps precedent | Ignore avec remote file was removed since the last BernOps export. |
| Le code du job est vide | Ignore et marque comme erreur. |
| Deux jobs resolvent le meme chemin d'export | Le doublon suivant est ignore et marque comme erreur. |
| La branche d'export BernOps existante a bouge de maniere inattendue | L'export echoue avec un conflit et demande de reessayer apres rafraichissement de l'etat PR. |
| La branche par defaut bouge pendant un export initial | L'export echoue au lieu d'ecrire des fichiers qui n'ont pas ete verifies contre les conflits. |
Quand BernOps met a jour une branche d'export existante, le backend transmet le SHA head precedemment suivi et met a jour la ref Git avec force = false. Cela evite d'ecraser silencieusement du travail ajoute a la branche d'export en dehors de BernOps.
Controle d'acces BernOps
BernOps protege les actions de gestion GitHub avec les memes controles de role projet que le reste de l'app.
| Action BernOps | Acces BernOps requis |
|---|---|
| Lire l'etat de connexion | Acces projet. |
| Lire l'arborescence du repository selectionne | Acces projet. |
| Lire les pull requests d'export suivies | Acces projet. |
| Creer l'URL d'installation GitHub | Acces proprietaire/admin espace. |
| Lister les repositories d'installation pour selection | Acces admin projet. |
| Selectionner ou remplacer la connexion repository | Acces admin projet. |
| Deconnecter le repository | Acces admin projet. |
| Exporter les tests vers GitHub | Acces admin projet. |
Les endpoints de configuration GitHub et de webhook sont des routes HTTP sans authentification utilisateur parce que GitHub les appelle directement. Ils ne sont pas des frontieres de confiance ouvertes : la configuration exige un etat signe et une validation du nonce stocke, et les webhooks exigent que la signature HMAC X-Hub-Signature-256 de GitHub corresponde au secret webhook configure.
Deconnexion et desinstallation
Deconnecter un repository dans BernOps supprime la connexion repository selectionnee pour le projet. L'installation GitHub App reste disponible au workspace, donc un admin projet peut reconnecter ce projet ou connecter un autre projet plus tard.
Quand une connexion repository est supprimee ou remplacee, BernOps remet a zero les metadonnees de synchronisation GitHub des jobs qui referencaient l'ancienne connexion. Si un verrou d'export est actif, les mutations de connexion et de deconnexion retournent un conflit au lieu de changer la connexion pendant que des ecritures GitHub sont en cours.
Si l'installation GitHub App est supprimee dans GitHub, le webhook installation fait supprimer la ligne d'installation locale dans BernOps. Comme les connexions repository referencent les installations avec ON DELETE CASCADE, les connexions repository de cette installation sont aussi supprimees.
Ce que BernOps ne fait pas
Ces affirmations refletent les chemins de code actuels de l'integration GitHub :
- BernOps ne merge pas les pull requests GitHub.
- BernOps n'ecrit pas directement sur la branche par defaut du repository.
- BernOps ne force-update pas les refs Git.
- BernOps ne demande pas de permissions d'organisation GitHub pour cette integration.
- BernOps n'utilise pas les APIs GitHub Actions, Secrets, Administration, Deployments, Packages, Members, Issues, Checks ou Workflows dans l'integration actuelle.
- BernOps ne stocke pas les tokens d'installation en base de donnees.
- BernOps ne conserve pas le token OAuth utilisateur de configuration apres finalisation de la configuration.
- BernOps ne stocke pas les corps bruts des payloads webhook GitHub dans la table des livraisons webhook.
- BernOps ne clone pas le repository connecte et n'execute pas son code pendant la connexion ou l'export.
References officielles
Documentation GitHub pour les comportements de plateforme pertinents :
- Choosing permissions for a GitHub App
- About authentication with a GitHub App
- Using webhooks with GitHub Apps
- Validating webhook deliveries
- Git trees REST API
- Git commits REST API
- Git references REST API
- Repository contents REST API
- Pull requests REST API
Pour les chemins REST BernOps exacts et les formes de reponse, ouvrez la Reference API et cherchez GitHub.