GitHub-Odoo Sync
1. Quoi ? — Définition et contexte
Section intitulée « 1. Quoi ? — Définition et contexte »Le workflow GitHub-Odoo Sync synchronise les événements GitHub (issues, commits, pull requests) avec les projets Odoo. Chaque issue GitHub devient une tâche Odoo, et chaque commit est enregistré dans l’historique.
Événements synchronisés
Section intitulée « Événements synchronisés »| Source | Direction | Destination |
|---|---|---|
| GitHub Issue | → | Odoo project.task |
| GitHub Commit | → | Odoo project.task.commit |
| GitHub PR | → | Odoo project.task (type PR) |
Composants impliqués
Section intitulée « Composants impliqués »| Composant | Rôle |
|---|---|
| GitHub Webhooks | Déclenchement des événements |
| N8N Workflow | Transformation et routage |
| Data Table | Mapping repo → projet Odoo |
| Odoo XML-RPC | API de création/mise à jour |
| Addon project_github_sync | Modèles étendus dans Odoo |
2. Pourquoi ? — Enjeux et motivations
Section intitulée « 2. Pourquoi ? — Enjeux et motivations »Problèmes résolus
Section intitulée « Problèmes résolus »| Problème | Sans sync | Avec sync |
|---|---|---|
| Visibilité métier | Issues visibles uniquement dans GitHub | Tâches visibles dans Odoo pour tous |
| Suivi du temps | Pas de lien issue → temps passé | Tâche Odoo liée aux timesheets |
| Historique commits | Dispersé dans GitHub | Centralisé sur la tâche Odoo |
| Double saisie | Créer tâche dans les deux systèmes | Automatique depuis GitHub |
Pourquoi cette direction (GitHub → Odoo) ?
Section intitulée « Pourquoi cette direction (GitHub → Odoo) ? »| Critère | Choix |
|---|---|
| Source de vérité | GitHub (là où le code vit) |
| Déclenchement | Webhooks GitHub (temps réel) |
| Enrichissement | Odoo ajoute le contexte business |
3. Comment ? — Mise en œuvre technique
Section intitulée « 3. Comment ? — Mise en œuvre technique »Architecture
Section intitulée « Architecture »┌─────────────────────────────────────────────────────────┐│ GitHub ││ ├─ Issues (opened, closed, edited, labeled...) ││ ├─ Pull Requests (opened, merged, closed) ││ └─ Push events (commits) │└─────────────────────┬───────────────────────────────────┘ │ Webhooks HMAC signés ▼┌─────────────────────────────────────────────────────────┐│ N8N: github-project-sync ││ ├─ Verify webhook signature ││ ├─ Switch by event type ││ ├─ Lookup mapping (Data Table) ││ ├─ Transform data ││ └─ Call Odoo XML-RPC │└─────────────────────┬───────────────────────────────────┘ │ XML-RPC ▼┌─────────────────────────────────────────────────────────┐│ Odoo 18 ││ ├─ project.project (repos liés) ││ ├─ project.task (issues synchro) ││ └─ project.task.commit (historique) │└─────────────────────────────────────────────────────────┘Configuration webhook GitHub
Section intitulée « Configuration webhook GitHub »GitHub → Settings → Webhooks
Payload URL: https://n8n.guigpap.com/webhook/githubContent type: application/jsonSecret: ${GITHUB_WEBHOOK_SECRET}
Events:☑ Issues☑ Push☑ Pull requestsData Table : github_project_mapping
Section intitulée « Data Table : github_project_mapping »| Colonne | Type | Description |
|---|---|---|
github_repo | Text | Format: owner/repo |
odoo_project_id | Integer | ID du projet Odoo |
sync_issues | Boolean | Synchroniser les issues |
sync_commits | Boolean | Synchroniser les commits |
sync_prs | Boolean | Synchroniser les PRs |
default_stage_id | Integer | Stage Odoo par défaut |
Événements supportés
Section intitulée « Événements supportés »Issues :
| Événement | Action Odoo |
|---|---|
opened | Créer project.task avec github_issue_id |
closed | Marquer la tâche comme terminée |
reopened | Réouvrir la tâche |
edited | Mettre à jour titre/description |
labeled | Ajouter tags correspondants |
assigned | Assigner l’utilisateur Odoo mappé |
Commits (Push) :
| Événement | Action Odoo |
|---|---|
push | Créer project.task.commit pour chaque commit |
Les commits référençant une issue (Fixes #123, Refs #45) sont liés à la tâche correspondante.
Pull Requests :
| Événement | Action Odoo |
|---|---|
opened | Créer tâche avec type “PR” |
merged | Marquer comme terminée + lier commits |
closed | Marquer comme annulée |
Flow détaillé : Issue opened
Section intitulée « Flow détaillé : Issue opened »GitHub webhook (issue opened) │ ▼┌─────────────────────────────────────────────────────────┐│ 1. Verify HMAC signature ││ X-Hub-Signature-256 vs computed hash │└───────────────────────┬─────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────┐│ 2. Lookup github_project_mapping ││ Key: "GuiGPaP/stacks_vps" ││ → odoo_project_id: 5 │└───────────────────────┬─────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────┐│ 3. Transform data ││ { ││ "name": "Issue #123: Fix login bug", ││ "project_id": 5, ││ "github_issue_id": 123, ││ "github_issue_url": "https://github.com/...", ││ "github_state": "open", ││ "description": "<html>...</html>" ││ } │└───────────────────────┬─────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────┐│ 4. Odoo XML-RPC: create ││ Model: project.task ││ → Returns task_id: 42 │└─────────────────────────────────────────────────────────┘Appels Odoo XML-RPC
Section intitulée « Appels Odoo XML-RPC »Créer une tâche :
const createResponse = await httpRequest({ url: 'http://odoo:8069/xmlrpc/2/object', method: 'POST', body: xmlrpc.call('execute_kw', [ 'odoo', // database uid, // user id 'password', // password 'project.task', // model 'create', // method [{ // values name: `Issue #${issue.number}: ${issue.title}`, project_id: mapping.odoo_project_id, github_issue_id: issue.number, github_issue_url: issue.html_url, github_state: 'open', description: transformedDescription }] ])});Mettre à jour une tâche :
// Rechercher la tâche par github_issue_idconst taskIds = await execute_kw('search', [ [['github_issue_id', '=', issue.number]]]);
// Mettre à jourawait execute_kw('write', [ taskIds, { github_state: 'closed', stage_id: doneStageId }]);Transformation Markdown → HTML
Section intitulée « Transformation Markdown → HTML »const { marked } = require('marked');
const description = marked.parse(issue.body || '');const fullDescription = ` <p><a href="${issue.html_url}">Voir sur GitHub #${issue.number}</a></p> ${description}`;Gestion des erreurs
Section intitulée « Gestion des erreurs »| Erreur | Comportement |
|---|---|
| Mapping non trouvé | Log warning, skip |
| Odoo inaccessible | Retry 3x, puis notification |
| Tâche non trouvée | Créer si opened, skip sinon |
| Signature invalide | Reject 401 |
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 | Odoo → GitHub pas implémenté | Prévu à terme |
| Mapping manuel | Chaque repo doit être configuré | Data Table à maintenir |
| Pas de sync labels | Tags Odoo non synchronisés | Mapping labels à implémenter |
Scénarios d’évolution
Section intitulée « Scénarios d’évolution »Si besoin de sync bidirectionnelle :
- Webhook Odoo → N8N quand tâche fermée
- N8N ferme l’issue GitHub correspondante
- Attention aux boucles infinies (flag
synced_from)
Si beaucoup de repos à gérer :
- Créer une interface de configuration dans Odoo
- Auto-découverte des repos GitHub d’une organisation
- Règles de mapping par pattern (
*-backend→ Projet Backend)
Si besoin de sync des PR plus avancée :
- Créer un type de tâche spécifique “Pull Request”
- Lier automatiquement les commits de la PR
- Mettre à jour le statut selon les checks CI
Pages liées
Section intitulée « Pages liées »Infrastructure
Section intitulée « Infrastructure »- Odoo 18 sur Docker — Configuration ERP
- Pourquoi Odoo — Choix et architecture
- N8N en mode Queue — Backend automation
Référence
Section intitulée « Référence »- Glossaire — XML-RPC, Webhook, HMAC