Revue de code automatique avec CodeRift
🇬🇧ENCodeRift analyse chaque merge request GitLab en 7 étapes : parsing de diff, AST tree-sitter, règles TOML, agents IA et commentaires inline automatiques.
La revue de code est le goulot d’étranglement de la plupart des équipes. La merge request est ouverte, l’auteur attend, le reviewer est sur autre chose. Quand la review arrive enfin, elle est souvent superficielle : un coup d’oeil sur le diff, un “LGTM”, merge. Les bugs de logique, les failles de sécurité et les violations d’architecture passent à travers.
J’ai construit CodeRift pour résoudre ce problème. C’est une plateforme de revue de code automatique qui analyse chaque merge request GitLab avec un pipeline en 7 étapes : parsing de diff, analyse AST via tree-sitter, moteur de règles TOML, agents IA spécialisés parallèles, corrélation cross-fichiers, validation des faux positifs, et publication des commentaires inline directement dans la MR. Le tout orchestré par IronFlow, mon moteur de workflows Rust.
L’architecture
CodeRift suit un modèle API + Workers. L’API (Rust/Axum/SQLx) gère la persistance, l’authentification GitLab OAuth et les webhooks. Les workers IronFlow interrogent l’API pour les reviews en attente, les exécutent, et postent les résultats.
La séparation API/Worker est la même que celle d’IronFlow : l’API possède la persistance et ne fait jamais d’exécution. Scaler, c’est lancer plus de workers.
Le pipeline de review en 7 étapes
Le workflow review-merge-request implémente le trait WorkflowHandler d’IronFlow. Chaque étape est une opération IronFlow avec retry automatique et logs structurés.
Étape 1-3 : Préparation
Le worker met à jour le statut de la review en base, poste une note “review en cours” sur la MR GitLab, et met le commit status à running. Le développeur voit immédiatement que la review IA est lancée.
ctx.operation("update-review-status", &update_status_op).await?;
ctx.http(
"post-review-started",
HttpConfig::post(¬es_url)
.header("PRIVATE-TOKEN", &CONFIG.gitlab.bot_token)
.json(serde_json::json!({ "body": review_started_message(language) })),
).await?;
commit_status::set(ctx, "set-commit-status-running", &proj,
&payload.head_sha, payload.review_id, "running",
"AI review in progress...").await?;
Étape 4 : Le pipeline de review (le coeur)
C’est ici que le travail se fait. Le pipeline suit cette séquence :
Règles TOML : CodeRift charge un ensemble de règles embarquées à la compilation (include_dir!). Chaque règle cible un langage, des patterns de fichiers, et définit un pattern regex avec des exceptions. Par exemple, la règle rust-unwrap détecte les .unwrap() dans le code de production en excluant les fichiers de test :
[[rules]]
id = "rust-unwrap"
severity = "error_handling"
score = 7
title = ".unwrap() in production code"
languages = ["rust"]
file_patterns = ["*.rs"]
exclude_patterns = ["*_test.rs", "tests/*"]
type = "regex"
pattern = '\.unwrap\(\)'
negative_pattern = '#\[test\]|#\[cfg\(test\)\]|mod tests'
Les règles couvrent Rust, TypeScript, Python, Go, SQL, et des patterns communs (OWASP, prompt injection). Chaque projet peut ajouter ses propres règles ou désactiver celles du serveur via un fichier .coderift/context.md.
Analyse AST : tree-sitter parse les fichiers modifiés et extrait un index de symboles (définitions, références, edges cross-fichiers). Cet index sert à deux choses : construire un graphe de dépendances pour grouper les fichiers liés dans les mêmes chunks, et détecter des patterns structurels que les regex ne voient pas.
Chunking : les fichiers sont regroupés en chunks de 5 (configurable) pour la review parallèle. Quand le graphe de dépendances est disponible, les fichiers liés restent dans le même chunk pour donner à l’agent le contexte des deux côtés d’une interface.
Agents IA spécialisés : chaque chunk est reviewé par 3 agents en parallèle, chacun avec un angle différent :
| Agent | Modèle | Focus |
|---|---|---|
| Sécurité | Opus 4.6 | Injections, XSS, SSRF, contrôle d’accès, secrets |
| Bugs | Opus 4.6 | Logique incorrecte, edge cases, erreurs de type |
| Performance | Sonnet 4.6 | N+1, allocations inutiles, complexité algorithmique |
Chaque agent a un budget en USD configurable et un maximum de 4 turns. Le provider IronFlow gère l’exécution et le tracking des coûts. Si un agent échoue (erreur de schéma, timeout), le pipeline continue avec les résultats des autres.
let mut agent = Agent::new()
.system_prompt(system)
.prompt(prompt)
.model(Model::OPUS_46)
.max_turns(4)
.max_budget_usd(budget)
.output::<FindingsOutput>();
Corrélation cross-fichiers : un agent Sonnet 4.6 reçoit tous les findings de tous les chunks et identifie les vulnérabilités qui traversent plusieurs fichiers. Par exemple, un input non validé dans un handler qui arrive dans une requête SQL dans un autre fichier.
Validation des faux positifs : un dernier agent filtre les findings non pertinents. Les faux positifs courants : un .unwrap() dans du code de test, un pattern flaggé dans un commentaire, un finding qui cible du code non modifié, ou un score gonflé par rapport au risque réel.
Étape 5-6 : Publication
Le worker poste les résultats dans la MR GitLab :
- Un résumé avec un walkthrough de la MR, les fichiers groupés par zone fonctionnelle, des diagrammes de séquence Mermaid pour les flux non triviaux, et des checks pre-merge (sécurité, gestion d’erreur, tests).
- Des commentaires inline sur les lignes concernées, avec la sévérité (Bug, Security, Performance, Error Handling, Suggestion), un score de criticité (Critical/Major/Moderate/Minor), et une suggestion de fix.
Étape 7 : Commit status
Le commit status GitLab passe à success ou failed. Si la review a des findings Critical, le pipeline peut bloquer le merge.
Les findings
Chaque finding a une structure précise :
pub struct Finding {
pub file: String,
pub line: u32,
pub end_line: Option<u32>,
pub severity: Severity, // Bug | Security | Performance | ErrorHandling | Suggestion
pub score: u8, // 0-10, convertible en Critical/Major/Moderate/Minor
pub title: String,
pub comment: String,
pub suggestion: Option<String>,
pub analysis_chain: Vec<String>,
pub ai_fix_prompt: Option<String>,
}
Le champ analysis_chain contient le raisonnement étape par étape de l’agent. Le champ ai_fix_prompt est un prompt prêt à l’emploi pour corriger le finding automatiquement.
Pourquoi pas un simple appel à Claude Code ?
La première version de ce système utilisait un node n8n qui invoquait Claude Code CLI. Ça fonctionnait pour les petites MR, mais les limites sont vite apparues :
- Pas de contexte structuré : Claude voyait un diff brut sans comprendre les relations entre fichiers
- Pas de règles : impossible d’encoder les conventions du projet de manière fiable
- Pas de déduplication : les mêmes findings revenaient en double ou triple
- Pas de contrôle de coût : un diff de 2000 lignes pouvait coûter 15 USD
- Pas de validation : aucun filtre sur les faux positifs
CodeRift résout chacun de ces problèmes. Le pipeline structuré (règles + AST + agents spécialisés + validation) produit des findings plus précis que l’approche “envoie tout le diff à un LLM et espère”.
Configuration par projet
Chaque projet peut personnaliser la review via .coderift/context.md :
# Architecture
4 couches strictes : rest, services, repositories, entities.
Violations à signaler :
- rest qui importe directement repositories
- services qui fait du SQL brut
- repositories qui contient de la logique métier
# Frontend
Les types API dans app/types/generated.ts sont auto-générés.
Ne jamais redéfinir manuellement un type qui existe dans ce fichier.
Ce fichier est injecté dans les prompts des agents comme contexte non fiable (sandboxé, sans possibilité d’altérer les instructions de review). Les agents l’utilisent pour comprendre les conventions du projet et flagger les violations spécifiques.
La stack
CodeRift est construit avec l’écosystème que j’ai développé : IronFlow pour l’orchestration des workflows, la même architecture en couches (entities/repositories/services/rest) que Netir, et MCP RTK en option pour réduire les tokens sur les serveurs MCP connectés. Le setup Claude Code et les skills que j’utilise au quotidien m’ont servi de base pour structurer les prompts de review de CodeRift.