Aller au contenu

GitHub-Odoo Sync

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.

SourceDirectionDestination
GitHub IssueOdoo project.task
GitHub CommitOdoo project.task.commit
GitHub PROdoo project.task (type PR)
ComposantRôle
GitHub WebhooksDéclenchement des événements
N8N WorkflowTransformation et routage
Data TableMapping repo → projet Odoo
Odoo XML-RPCAPI de création/mise à jour
Addon project_github_syncModèles étendus dans Odoo

ProblèmeSans syncAvec sync
Visibilité métierIssues visibles uniquement dans GitHubTâches visibles dans Odoo pour tous
Suivi du tempsPas de lien issue → temps passéTâche Odoo liée aux timesheets
Historique commitsDispersé dans GitHubCentralisé sur la tâche Odoo
Double saisieCréer tâche dans les deux systèmesAutomatique depuis GitHub
CritèreChoix
Source de véritéGitHub (là où le code vit)
DéclenchementWebhooks GitHub (temps réel)
EnrichissementOdoo ajoute le contexte business

┌─────────────────────────────────────────────────────────┐
│ 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) │
└─────────────────────────────────────────────────────────┘
GitHub → Settings → Webhooks
Payload URL: https://n8n.guigpap.com/webhook/github
Content type: application/json
Secret: ${GITHUB_WEBHOOK_SECRET}
Events:
☑ Issues
☑ Push
☑ Pull requests
ColonneTypeDescription
github_repoTextFormat: owner/repo
odoo_project_idIntegerID du projet Odoo
sync_issuesBooleanSynchroniser les issues
sync_commitsBooleanSynchroniser les commits
sync_prsBooleanSynchroniser les PRs
default_stage_idIntegerStage Odoo par défaut

Issues :

ÉvénementAction Odoo
openedCréer project.task avec github_issue_id
closedMarquer la tâche comme terminée
reopenedRéouvrir la tâche
editedMettre à jour titre/description
labeledAjouter tags correspondants
assignedAssigner l’utilisateur Odoo mappé

Commits (Push) :

ÉvénementAction Odoo
pushCré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énementAction Odoo
openedCréer tâche avec type “PR”
mergedMarquer comme terminée + lier commits
closedMarquer comme annulée
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 │
└─────────────────────────────────────────────────────────┘

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_id
const taskIds = await execute_kw('search', [
[['github_issue_id', '=', issue.number]]
]);
// Mettre à jour
await execute_kw('write', [
taskIds,
{ github_state: 'closed', stage_id: doneStageId }
]);
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}
`;
ErreurComportement
Mapping non trouvéLog warning, skip
Odoo inaccessibleRetry 3x, puis notification
Tâche non trouvéeCréer si opened, skip sinon
Signature invalideReject 401

LimiteImpactMitigation
UnidirectionnelOdoo → GitHub pas implémentéPrévu à terme
Mapping manuelChaque repo doit être configuréData Table à maintenir
Pas de sync labelsTags Odoo non synchronisésMapping labels à implémenter

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