Repository navigation
[GH-P3] Webhook app-level : HMAC, anti-rejeu, routage d'événements, handle_push partagé - #235
Merged
Merged
Conversation
…ing, shared handle_push)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[GH-P3] Webhook app-level : signature, anti-rejeu, routage d'événements
Plan :
devforge-plan-github-app.md, phase P3. S'appuie sur P0–P2.Checklist
POST /api/v1/webhooks/github-app(github_app_events.rs, montée dansmain.rs). L'ancienne/api/v1/webhooks/githubgarde la même signature/HMAC/bypass lab.webhook_secretdescellé,hmac::verify_slice(temps constant). En-tête absent ⇒ 401. Aucun bypass (DEVFORGE_ALLOW_INSECURE_WEBHOOKignoré, testé). Pas d'app ⇒ 503.DefaultBodyLimit25 Mo sur cette route.X-GitHub-Delivery→github_webhook_deliveries(ON CONFLICT DO NOTHING). Si déjà vu ⇒ 200{"duplicate":true}sans retraitement. Purge > 7 jours dansauto_deploy::tick.installation.id∉github_installations⇒ 202 ignoré + log (saufinstallation.created, qui la crée).repository.id↔projects.github_repo_idvérifié au push.accepted) ; le traitement tourne danstokio::spawn, avec statut final +duration_mspar livraison.installation:created(+ dépôts),new_permissions_accepted,suspend/unsuspend,deleted(installation + dépôts supprimés). Les projets sont conservés et comptés dansdisconnected_projects(statutGET /api/v1/github-app, pour l'alerte UI).installation_repositoriesadded/removed⇒ mise à jour degithub_installation_repos.push⇒ la logique degithub_webhookest extraite danshandle_push(state, payload, scope), partagée par les deux routes. Suppressions de branche (deleted:true) et tags ignorés.pull_request⇒ enregistré et ignoré jusqu'à P5.check_run.rerequested/check_suite.rerequested⇒ redéploiement de la branchehead_branch(push synthétique vershandle_push).GET /api/v1/github-app/deliveries(admin) : 20 dernières livraisons (id, événement, action, statut, durée, installation, date), sans payload.Anti double déploiement (migration)
PushScope::Legacy(ancien webhook) cible tous les projets du dépôt, sauf ceux liés à une installation quand le mode App est actif.PushScope::Installation(id)(nouveau) ne cible que les projets liés à cette installation et à cerepository.id. Sans mode App, l'ancien webhook est strictement inchangé (testé). Aucun projet n'est lié aujourd'hui (le lien arrive en P6/P7), donc rien ne change en prod.Tests
duplicate).installation.createdaccepté ;ping⇒ 200.apps/server/tests/fixtures/github/*.json: push, push supprimé, installation created/suspend/unsuspend/deleted, installation_repositories added/removed, check_run/check_suite rerequested, pull_request, ping) ⇒ effets en base vérifiés, dontdisconnected_projectsaprèsdeleted.handle_push: non-régression de la sélection des projets pour les deux routes (Legacy sans/avec mode App, Installation), suppression/tag ignorés.cargo test --workspace⇒ 627 passés, 0 échec.Validation (manuelle, après création de l'app en prod)
« Redeliver » depuis la page Advanced de l'app ⇒ visible
duplicate. Push surmaind'un repo installé ⇒ déploiement < 5 s après réception. Pas encore faite : il faut d'abord l'app en prod (P1) et un projet lié.Risques
check_*.rerequestedredéploie la tête de branche, pas strictementhead_sha(run_real_deploydéploie la branche). Les deux ne divergent que si la branche a avancé entre-temps. À affiner en P4.handle_push(déploiement) tourne en tâche détachée : en cas de redémarrage du serveur pendant le traitement, la livraison restereceived. GitHub ne la renverra pas d'elle-même (pas de retry 2xx) ; il faut la relancer à la main.deleted:trueet les tags est un léger changement : un push de suppression de la branche suivie ne déclenche plus de déploiement voué à l'échec.