La plupart des équipes API traitent le contrat trop tard : elles écrivent le code, génèrent une spécification, puis constatent que les deux divergent. Une approche API “git-native” inverse l’ordre : le contrat API devient un fichier source, versionné dans Git, revu en pull request et utilisé comme base pour les mocks, tests, clients et documentation.
Ce guide décrit un flux de travail pratique : concevoir les contrats dans des branches, les valider avec des revues, puis générer les artefacts en aval à partir de la spécification acceptée. L’objectif : faire de votre historique Git l’historique réel de votre API.
Si vous voulez une présentation produit du workflow, lisez aussi l’article sur le flux de travail API “git-native”. Ici, on reste concentré sur l’implémentation.
Ce que signifie “git-native” pour le travail API
“Git-native” signifie que votre définition API vit dans votre dépôt sous forme de fichier texte : openapi.yaml, openapi.json, fichiers AsyncAPI, .proto, SDL GraphQL, etc.
Elle n’est pas uniquement stockée dans une base cloud propriétaire. Elle n’est pas seulement exportée depuis une interface. Elle est versionnée avec le même système que votre code.
Dans ce modèle, le fichier présent dans main est le contrat canonique. Les interfaces graphiques, générateurs, mocks, tests et portails de documentation ne sont que des vues ou des sorties dérivées de ce fichier.
Une configuration API “git-native” respecte trois règles :
- La spécification est un fichier texte dans le dépôt.
- Chaque changement passe par Git : branche, commit, pull request, merge.
- Les artefacts en aval sont générés depuis la version validée, pas depuis une base séparée.
Pourquoi concevoir et développer des API dans Git
Vous utilisez déjà Git pour protéger votre code. Le contrat API mérite le même niveau de discipline.
Historique
Pour répondre à une question comme “quand avons-nous ajouté le paramètre cursor ?”, vous utilisez simplement :
git log -p -- api/openapi.yaml
Vous obtenez le commit, l’auteur, la date et le contexte.
Responsabilité
Avec git blame, vous voyez quelle PR a introduit une route, un champ ou une valeur d’énumération :
git blame api/openapi.yaml
La discussion de conception reste attachée au changement.
Retour arrière
Si une mauvaise décision est fusionnée, vous pouvez revenir en arrière :
git revert <merge_commit_sha>
Les mocks, clients, tests et documentations se régénèrent ensuite depuis l’état précédent du contrat.
Revue de conception
Une pull request est l’endroit idéal pour débattre d’un endpoint avant son implémentation. Les relecteurs peuvent commenter une ligne qui ajoute un champ requis, une nouvelle réponse ou une valeur d’énumération.
C’est le principe clé d’un flux de travail de spécification API basé sur Git : une source unique de vérité, lisible et révisable.
La boucle de conception API “git-native”
Le workflow tient en cinq étapes :
- Créer une branche.
- Modifier le contrat.
- Commiter la spécification.
- Ouvrir une pull request.
- Réviser puis fusionner.
L’implémentation vient après l’accord sur le contrat.
Exemple : ajout d’un endpoint pour lister les factures d’un utilisateur.
# api/openapi.yaml
paths:
/users/{userId}/invoices:
get:
operationId: listUserInvoices
summary: List invoices for a user
parameters:
- name: userId
in: path
required: true
schema:
type: string
format: uuid
- name: status
in: query
required: false
schema:
type: string
enum: [draft, open, paid, void]
responses:
"200":
description: A page of invoices
content:
application/json:
schema:
$ref: "#/components/schemas/InvoiceList"
"404":
description: User not found
Créez une branche dédiée :
git checkout -b feat/api-invoices-list
Validez un commit court et explicite :
git add api/openapi.yaml
git commit -m "Add GET /users/{userId}/invoices contract"
Ouvrez ensuite une pull request. Les relecteurs doivent vérifier :
- le nom du chemin ;
- les paramètres ;
- les valeurs d’énumération ;
- les codes de réponse ;
- les schémas de réponse ;
- les impacts consommateurs.
Une fois la PR approuvée, fusionnez. Le contrat dans main contient maintenant le nouvel endpoint. L’équipe peut implémenter le backend, générer des clients et exposer un mock à partir du même fichier.
C’est le principe du développement API “spec-first” : l’accord précède le code.
Stratégie de branchement pour les contrats API
Gardez les changements petits. Une branche doit représenter une unité logique : un endpoint, un champ, une correction ou une refactorisation.
| Type de changement | Préfixe de branche | Exemple | Poids de la revue |
|---|---|---|---|
| Nouvel endpoint | feat/api- |
feat/api-invoices-list |
Standard |
| Champ additif | feat/api- |
feat/api-invoice-currency |
Léger |
| Changement cassant | break/api- |
break/api-remove-legacy-id |
Lourd, approbation requise |
| Correction dans la spécification | fix/api- |
fix/api-status-enum-typo |
Léger |
| Refactorisation uniquement | chore/api- |
chore/api-reorder-schemas |
Léger |
Le préfixe donne un signal immédiat. Une branche break/api- force les relecteurs à vérifier les impacts consommateurs. Une branche chore/api- indique qu’aucun changement sémantique n’est attendu.
Deux modèles sont courants :
| Modèle | Idéal pour | Compromis API |
|---|---|---|
| Développement basé sur le tronc | Livraison continue, petites équipes | Contrat modifié par petites étapes, moins de conflits |
| Gitflow | Versions planifiées, contraintes réglementaires | Spécification plus susceptible de diverger, merges plus lourds |
Pour la plupart des équipes, privilégiez le développement basé sur le tronc : branches courtes, PR petites, merges fréquents. Les branches longues augmentent le risque de conflits YAML et de divergence de conception.
Réviser une conception API dans une pull request
Une PR de spécification n’est pas seulement une vérification syntaxique. C’est une revue de design.
Les relecteurs doivent poser ces questions.
Le changement casse-t-il des consommateurs ?
Sont cassants :
- suppression d’un champ ;
- renommage d’un chemin ;
- changement de type ;
- champ optionnel devenu requis ;
- suppression d’une valeur d’énumération ;
- changement de format de réponse.
Un changement cassant doit être visible dans la PR, accompagné d’une stratégie de versioning ou de dépréciation.
Le nommage est-il cohérent ?
Vérifiez les conventions existantes :
- noms de ressources au pluriel ou singulier ;
- format des IDs ;
- noms des paramètres de pagination ;
- structure des erreurs ;
- casing des champs JSON ;
- cohérence des
operationId.
Le diff est-il lisible ?
Un contrat API doit rester “diff-friendly”. Évitez de réordonner tout un fichier si vous ajoutez seulement une route.
Exemple de diff clair :
parameters:
- name: status
in: query
schema:
type: string
- enum: [draft, open, paid, void]
+ enum: [draft, open, paid, void, uncollectible]
Ici, le changement est additif : une nouvelle valeur est ajoutée. La revue est rapide.
À l’inverse, supprimer void serait cassant pour les clients qui l’envoient déjà.
De la conception au développement
Une fois le contrat fusionné dans main, il devient la base des artefacts en aval.
Générer le code
Des outils comme openapi-generator peuvent produire des stubs serveur ou des clients typés :
openapi-generator-cli generate \
-i api/openapi.yaml \
-g typescript-fetch \
-o generated/client
Ou pour un serveur :
openapi-generator-cli generate \
-i api/openapi.yaml \
-g nodejs-express-server \
-o generated/server
Le code métier reste à écrire, mais les formes de requêtes et réponses viennent du contrat.
Fournir des mocks
Un serveur de mock lit la spécification et renvoie des réponses d’exemple. Le frontend peut commencer sans attendre que le backend soit terminé.
Le workflow devient :
- contrat fusionné ;
- mock généré ;
- frontend développé contre le mock ;
- backend implémenté ;
- tests de contrat exécutés.
Ajouter des tests de contrat
Les tests de contrat vérifient que le serveur réel respecte la spécification validée.
Exemple de logique :
Envoyer une requête réelle
Comparer la réponse au schéma OpenAPI
Faire échouer la CI si la réponse diverge
C’est la meilleure défense contre la dérive entre spécification et code.
Générer la documentation
La documentation de référence doit être rendue depuis openapi.yaml. Quand le contrat change, la documentation change dans le même cycle.
Le principe reste le même : ne maintenez pas plusieurs vérités. Générez à partir du fichier validé.
Conventions d’équipe qui évoluent
Un workflow “git-native” fonctionne si l’équipe écrit ses conventions et les automatise.
1. Choisir une structure de fichiers
Option simple :
api/
openapi.yaml
Pratique au début, mais difficile à maintenir quand l’API grandit.
Option modulaire :
api/
openapi.yaml
paths/
users.yaml
invoices.yaml
schemas/
user.yaml
invoice.yaml
Avec des références :
$ref: "./schemas/invoice.yaml"
Cette approche rend les PR plus lisibles, car chaque ressource a son fichier.
2. Versionner explicitement
Mettez à jour info.version pour chaque changement significatif.
info:
title: Billing API
version: 1.4.0
Règle pratique :
- changement additif : version mineure ;
- correction sans impact consommateur : patch ;
- changement cassant : version majeure, souvent avec un chemin
/v2.
3. Maintenir un changelog
Ajoutez un CHANGELOG.md près de la spécification :
# Changelog
## 1.4.0
- Add `GET /users/{userId}/invoices`
- Add `uncollectible` invoice status
## 1.3.1
- Fix typo in `status` enum description
Git est précis, mais le changelog est plus lisible pour les consommateurs.
4. Protéger la spécification avec CODEOWNERS
Exigez l’approbation des responsables API :
# .github/CODEOWNERS
/api/openapi.yaml @api-stewards
/api/paths/ @api-stewards
/api/schemas/ @api-stewards
Ainsi, aucun changement de contrat ne passe sans revue spécialisée.
5. Linter la spécification en CI
Utilisez un linter pour automatiser les règles de style et de cohérence.
Exemple avec Spectral et GitHub Actions :
# .github/workflows/api-lint.yml
name: API Lint
on:
pull_request:
paths:
- "api/**"
jobs:
spectral:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Spectral
run: npx @stoplight/spectral-cli lint api/openapi.yaml --fail-severity warn
Avec CODEOWNERS et un linter CI, les humains se concentrent sur la conception, pas sur le formatage.
Pièges courants et comment les éviter
Dérive entre spécification et code
Problème : le contrat dit une chose, le serveur en fait une autre.
Solution : ajoutez des tests de contrat en CI. Si la réponse réelle ne correspond pas au schéma OpenAPI, la build échoue.
Pull requests trop grandes
Problème : une PR ajoute vingt endpoints. Personne ne la relit correctement.
Solution : une PR par endpoint ou par changement logique. Les petits diffs obtiennent de vraies revues.
Artefacts écrits à la main
Problème : un client ou une documentation maintenu à la main diverge du contrat.
Solution : générez clients, stubs, mocks et documentation depuis la spécification validée.
Conflits YAML fréquents
Problème : plusieurs branches longues modifient les mêmes zones du fichier.
Solution :
- branches courtes ;
- ordre stable des clés ;
- fichiers séparés par ressource ;
- merges fréquents dans
main.
La discipline principale est simple : petits changements, artefacts générés, CI stricte.
Où Apidog s’intègre
Vous pouvez exécuter ce workflow avec un éditeur de texte et une CLI. Certaines équipes veulent aussi une interface graphique pour concevoir l’API sans abandonner Git comme source de vérité.
C’est le rôle du Mode Spec-First d’Apidog.
Le Mode Spec-First conserve le fichier OpenAPI dans votre dépôt Git et prend en charge une synchronisation bidirectionnelle. Vous pouvez modifier le contrat dans le concepteur visuel d’Apidog ou dans votre éditeur, tout en gardant le fichier Git comme version canonique.
Les branches, pull requests, merges et historiques restent donc ceux de Git. Apidog devient une vue de conception sur le contrat, pas une source de vérité séparée.
Consultez la documentation du Mode Spec-First pour les détails de configuration.
FAQ
La conception API “git-native” est-elle limitée à OpenAPI ?
Non. Le principe s’applique à tout contrat textuel : OpenAPI, AsyncAPI, fichiers .proto gRPC ou SDL GraphQL. Tant que le fichier peut être versionné, différencié et revu dans Git, il peut entrer dans un workflow “git-native”.
Comment gérer les changements cassants ?
Rendez-les visibles :
- branche avec préfixe
break/api-; - mise à jour majeure de
info.version; - approbation obligatoire via
CODEOWNERS; - changelog explicite ;
- stratégie de dépréciation si possible.
Quand c’est possible, ajoutez la nouvelle forme à côté de l’ancienne avant de retirer l’ancienne.
La spécification doit-elle être dans le même dépôt que le code ?
Oui, dans la plupart des cas, surtout si une seule équipe possède l’API et son implémentation. Une seule PR peut alors modifier le contrat, le code et les tests.
Un dépôt séparé est utile si plusieurs équipes consomment une API partagée et ont besoin d’un versioning indépendant.
Comment empêcher la spécification et le code de diverger ?
Combinez trois pratiques :
- Générer les stubs et clients depuis la spécification.
- Exécuter des tests de contrat en CI.
- Faire échouer la build si le serveur ne respecte pas le contrat.
La dérive devient alors un problème détecté par pipeline, pas une surprise en production.
Conclusion
La conception API “git-native” est une discipline : traiter le contrat comme du code source, le faire évoluer dans des branches, le relire en pull request et générer les artefacts en aval depuis le fichier validé.
Commencez simplement :
- placez la spécification dans le dépôt ;
- ajoutez un linter CI ;
- imposez une revue avec
CODEOWNERS; - générez les mocks, clients et docs ;
- ajoutez des tests de contrat.
Chaque étape renforce la suivante. À terme, votre historique Git devient l’enregistrement complet de l’évolution de votre API.
Si vous voulez une interface visuelle tout en gardant Git comme source de vérité, essayez le Mode Spec-First dans Apidog et vérifiez comment la synchronisation bidirectionnelle s’intègre à ce workflow.


Top comments (0)