GitHub-Odoo Sync
1. Quoi ? — Définition et contexte
Section intitulée « 1. Quoi ? — Définition et contexte »Le workflow GitHub-Odoo Sync transforme chaque événement GitHub (issue, PR, commit) en une opération Odoo correspondante : tâche projet créée, label appliqué, milestone synchronisé, commit historisé. Depuis le refactoring #274, l’architecture est passée d’un workflow monolithique de 138 nodes à un hub de 13 nodes qui dispatche vers 7 sous-workflows spécialisés.
Architecture hub-spoke
Section intitulée « Architecture hub-spoke »| Workflow | ID | Nodes | Rôle |
|---|---|---|---|
| GitHub Project Sync (parent) | JR8ESduxKNSQ7iVs | 13 | Trigger + lookup mapping + dispatch par event type |
| SW-1 Issue Lifecycle | 8yU07chLmZuogA3j | 23 | opened / closed / reopened + sub-issues parent |
| SW-2 Issue Labels | OMeuYvh0B9XA2S1H | 11 | labeled / unlabeled |
| SW-3 Issue Properties | 0BoSdwR4d8S9Fq0C | 32 | assigned / edited / pinned / renamed / deleted |
| SW-4 Issue Milestone | EZiZqgZNpxEzof7F | 13 | milestoned / demilestoned |
| SW-5 PR Handler | 3o7IzU2brzJeedB7 | 18 | pull_request opened / merged / closed |
| SW-6 Git Events | O2jirkOJOpOIy5ez | 18 | push (commits) + create (branch stage transition) |
| SW-7 Repo Entity | WVWY01qmw9uYzSl8 | 28 | Label + Milestone CRUD au niveau du repo |
Dépendance partagée
Section intitulée « Dépendance partagée »Un sous-workflow utilitaire odoo-get-or-create-tag (j7e2EzEtIJ42T2S4) est appelé par SW-1, SW-2 et SW-7 pour créer ou récupérer des tags Odoo correspondant aux labels GitHub.
Architecture visuelle
Section intitulée « Architecture visuelle »Événements supportés
Section intitulée « Événements supportés »Tous les événements GitHub utiles à un workflow projet sont synchronisés :
| Catégorie | Événements | Sous-workflow |
|---|---|---|
| Cycle de vie issue | opened, closed, reopened | SW-1 |
| Sub-issues | parent_added, parent_removed | SW-1 |
| Labels issue | labeled, unlabeled | SW-2 |
| Propriétés issue | assigned, edited, pinned, renamed, deleted | SW-3 |
| Milestone issue | milestoned, demilestoned | SW-4 |
| Pull requests | opened, closed, merged | SW-5 |
| Push & branches | push (commits), create (branch) | SW-6 |
| Repo-level | label/milestone CRUD | SW-7 |
2. Pourquoi ? — Enjeux et motivations
Section intitulée « 2. Pourquoi ? — Enjeux et motivations »Le problème sans synchro
Section intitulée « Le problème sans synchro »| Sans sync | Conséquence |
|---|---|
| Visibilité métier | Les issues restent invisibles depuis Odoo |
| Suivi du temps | Impossible de lier une heure de timesheet à une issue précise |
| Historique commits | Dispersé dans GitHub, pas de vue cumulée par tâche Odoo |
| Double saisie | Créer une tâche Odoo manuellement pour chaque issue |
Pourquoi un hub-spoke plutôt qu’un workflow unique ?
Section intitulée « Pourquoi un hub-spoke plutôt qu’un workflow unique ? »Le workflow d’origine (138 nodes) avait grossi au fil des événements supportés. Trois symptômes ont déclenché le refactoring #274 :
| Symptôme | Cause | Conséquence |
|---|---|---|
| Édition lente | UI N8N peine à charger 138 nodes | Modifs ergonomiquement coûteuses |
| Tests rébarbatifs | Touche un sub-flow → re-tester le tout | Régressions silencieuses |
| Couplage | Code IA tag, Odoo task, milestone partagés | Changement local cassait des branches lointaines |
L’architecture en hub avec 7 sous-workflows résout ces tensions : chaque SW a un périmètre étroit, peut être édité et testé isolément, et signe son contrat d’I/O via Execute Workflow Trigger.
Pourquoi GitHub → Odoo et pas l’inverse ?
Section intitulée « Pourquoi GitHub → Odoo et pas l’inverse ? »| Critère | Choix |
|---|---|
| Source de vérité du code | GitHub (là où vivent les commits, les PRs, les CI) |
| Source de vérité business | Odoo (timesheets, factures, projets clients) |
| Direction du déclenchement | GitHub webhooks (temps réel, sub-second) |
| Enrichissement | Odoo ajoute le contexte business (projet, tags, complexité, estimation) |
La direction inverse (fermer une issue depuis Odoo) est techniquement faisable mais ajoute un risque de boucle. Pour le moment, GitHub reste source ; Odoo est sink + dashboard.
3. Comment ? — Mise en œuvre technique
Section intitulée « 3. Comment ? — Mise en œuvre technique »Le parcours d’un événement
Section intitulée « Le parcours d’un événement »1. Webhook GitHub — Le trigger N8N reçoit l’événement avec sa signature HMAC X-Hub-Signature-256 (vérifiée par N8N).
2. Lookup mapping — Le hub consulte la Data Table github_project_mapping pour trouver le projet Odoo associé au repo (owner/repo → odoo_project_id).
3. Switch event type — Le hub route vers le sous-workflow adapté selon headers.x-github-event et body.action.
4. Sub-workflow execution — Chaque SW reçoit en passthrough {body, headers, query, mapping} et applique sa logique métier.
5. Appels Odoo XML-RPC — Tous les SWs convergent vers le même endpoint Odoo : http://odoo:8069/xmlrpc/2/object, base de données guig_db.
Module Odoo project_github_sync
Section intitulée « Module Odoo project_github_sync »L’addon custom project_github_sync (v18.0.5.6.0) ajoute les champs nécessaires à la synchro. Tous les champs custom utilisent le préfixe x_ pour ne pas entrer en collision avec les natifs Odoo :
Champs sur project.task
Section intitulée « Champs sur project.task »| Famille | Champ | Type | Source |
|---|---|---|---|
| GitHub | x_github_issue_id | Integer (indexé) | numéro issue/PR |
| GitHub | x_github_url | Char(500) | URL GitHub |
| GitHub | x_github_repo | Char (indexé) | owner/repo |
| GitHub | x_github_milestone_id | Integer | numéro milestone |
| GitHub | x_github_parent_issue_id | Integer | parent (sub-issues) |
| GitHub | x_github_commit_ids | One2many | commits liés |
| Effort (#188) | x_estimated_hours | Float(10,2) | estimation à la création |
| Effort (#188) | x_complexity | Selection | trivial / simple / moderate / complex |
| AI triage (#296) | x_ai_project_triaged_at | Datetime | dernière analyse projet (TTL 7j) |
| AI triage (#296) | x_ai_personal_triaged_at | Datetime | dernière analyse perso (TTL 7j) |
| Telemetry | x_claude_time_total | Float(10,2) | temps actif Claude Code |
| Telemetry | x_claude_cost_total | Float(10,4) | coût API USD |
| Telemetry | x_claude_token_total | Integer | tokens cumulés |
| Telemetry | x_claude_sessions | Integer | nombre de sessions |
| Telemetry | x_claude_lines_added/removed | Integer | LOC delta |
| Telemetry | x_claude_session_ids | One2many | historique sessions |
| Telemetry | x_claude_category | Selection | catégorie auto pour tâches génériques |
Modèles ajoutés
Section intitulée « Modèles ajoutés »| Modèle | Rôle |
|---|---|
project.task.github.commit | Un enregistrement par commit lié à une tâche (sha, message, auteur, date) |
project.task.claude.session | Un enregistrement par session Claude Code (id, durée, coût, tldr, category) |
Issue Lifecycle (SW-1) en détail
Section intitulée « Issue Lifecycle (SW-1) en détail »Le sous-workflow le plus chargé est SW-1 Issue Lifecycle, qui gère 5 actions distinctes :
Estimation d’effort à la création (#188)
Section intitulée « Estimation d’effort à la création (#188) »Quand une nouvelle issue est créée, SW-1 dérive automatiquement deux champs depuis le titre + body :
| Champ | Calcul |
|---|---|
x_complexity | Heuristique sur la longueur du body, mots-clés (refactor, migration, multi-step) |
x_estimated_hours | Modèle déterministe basé sur la cohorte de complexité (cf. Effort Estimator V1) |
L’estimation initiale est une borne basse qui sert de référence. Le champ effective_hours (timesheets agrégés) permet ensuite de mesurer l’écart estimation vs réalité, alimentant un weekly coverage report.
Daily GitHub Triage + AI double-triage
Section intitulée « Daily GitHub Triage + AI double-triage »En parallèle de la synchro événementielle, un workflow planifié quotidien (61uBaaFQssxT1HJ0, 25 nodes) effectue un rattrapage et un triage AI :
| Étape | Action |
|---|---|
| 1. Sync de rattrapage | Récupère les issues GitHub modifiées depuis 24h, met à jour Odoo |
| 2. Stage promotion | Si une issue est in progress côté GitHub mais Backlog côté Odoo → promu à In Progress |
| 3. AI Issue Triage (#296) | Sub-workflow AwqOyyAC3sUg9tSm (12n) — codex-yolo analyse l’issue et propose stage projet + horizon perso |
| 4. Cache TTL 7j | Les champs x_ai_*_triaged_at empêchent de re-triager une issue déjà analysée récemment |
Le triage AI est aussi exposé en mode interactif via l’API triage-interactive-api consommée par Claude Code lors d’une session ouverte (commande /triage).
Format des données passées
Section intitulée « Format des données passées »Le hub passe à chaque sous-workflow un objet uniforme :
{ "body": { /* GitHub webhook payload */ }, "headers": { "x-github-event": "issues", "x-github-delivery": "..." }, "query": {}, "mapping": { "github_repo": "owner/repo", "odoo_project_id": 5, "default_stage_id": 21, "sync_enabled": true }}Le contrat d’entrée est strict (Execute Workflow Trigger en mode passthrough désactivé pour SW-3 à SW-7 qui utilisent des workflowInputs typés).
Initial Sync (#50)
Section intitulée « Initial Sync (#50) »Pour intégrer un repo existant qui contient déjà des centaines d’issues, le workflow Initial Sync (#50) permet une importation one-shot : pagination GitHub API + création séquentielle des tâches Odoo + setup des tags. À utiliser uniquement à la mise en place ; ensuite, le sync événementiel suffit.
4. Et si ? — Perspectives et limites
Section intitulée « 4. Et si ? — Perspectives et limites »Limites actuelles
Section intitulée « Limites actuelles »| Limite | Impact | Mitigation |
|---|---|---|
| Unidirectionnel | Fermer côté Odoo ne ferme pas l’issue GitHub | Sync inverse à concevoir avec flag anti-boucle |
| Mapping manuel | Chaque repo doit être ajouté à la Data Table | Auto-discovery par organisation à terme |
| Estimation initiale = borne basse | Issues complexes sous-estimées | Recalibrage hebdomadaire prévu via cohort matching |
| Triage AI 24h de retard max | Re-triage le lendemain si issue ignorée | Acceptable, le triage est un assistant pas un oracle |
Scénarios d’évolution
Section intitulée « Scénarios d’évolution »Si besoin de sync bidirectionnelle :
- Webhook Odoo
automation.actionquand une tâche passe en stageDone - Le webhook fait un commentaire GitHub
Closed via Odoo task #N - Flag
synced_from_odoodans la table de mapping pour bloquer la rétro-propagation
Si beaucoup de repos à gérer :
- Auto-discovery des repos d’une organisation GitHub
- Templates de mapping par convention de nom (
*-backend→ projet Backend) - UI Odoo dédiée pour configurer les mappings sans toucher la Data Table
Si le triage AI devient critique :
- Activer un mode confiance haute (auto-set du stage si
confidence > 0.9) - Logger les décisions dans
claude_code_active_sessionspour audit - Permettre un override manuel via
/triage <issue> <stage>
Pages liées
Section intitulée « Pages liées »Infrastructure
Section intitulée « Infrastructure »- Odoo 18 sur Docker — Module project_github_sync, champs x_*
- Pourquoi Odoo — Choix et architecture
- N8N en mode Queue — Backend qui exécute les sub-workflows
Workflows
Section intitulée « Workflows »- Claude Code Telemetry — Alimente les champs x_claude_*
- Monitoring Digests — Effort Estimator V1, Daily Todo Digest, Daily GitHub Triage
- Error Handler — Capture les erreurs des 7 sub-workflows
Référence
Section intitulée « Référence »- Glossaire — XML-RPC, Webhook, HMAC, Sub-workflow