DEV Community

Cover image for Comment concevoir et développer des API selon l'approche Git-native
Antoine Laurent
Antoine Laurent

Posted on • Originally published at apidog.com

Comment concevoir et développer des API selon l'approche Git-native

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.

Essayez Apidog aujourd’hui

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.

Comparaison entre workflow API cloud-locked et git-native

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 :

  1. La spécification est un fichier texte dans le dépôt.
  2. Chaque changement passe par Git : branche, commit, pull request, merge.
  3. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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 :

  1. Créer une branche.
  2. Modifier le contrat.
  3. Commiter la spécification.
  4. Ouvrir une pull request.
  5. 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
Enter fullscreen mode Exit fullscreen mode

Créez une branche dédiée :

git checkout -b feat/api-invoices-list
Enter fullscreen mode Exit fullscreen mode

Validez un commit court et explicite :

git add api/openapi.yaml
git commit -m "Add GET /users/{userId}/invoices contract"
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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.

Workflow de génération depuis la spécification API

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
Enter fullscreen mode Exit fullscreen mode

Ou pour un serveur :

openapi-generator-cli generate \
  -i api/openapi.yaml \
  -g nodejs-express-server \
  -o generated/server
Enter fullscreen mode Exit fullscreen mode

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 :

  1. contrat fusionné ;
  2. mock généré ;
  3. frontend développé contre le mock ;
  4. backend implémenté ;
  5. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Avec des références :

$ref: "./schemas/invoice.yaml"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 :

  1. Générer les stubs et clients depuis la spécification.
  2. Exécuter des tests de contrat en CI.
  3. 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 :

  1. placez la spécification dans le dépôt ;
  2. ajoutez un linter CI ;
  3. imposez une revue avec CODEOWNERS ;
  4. générez les mocks, clients et docs ;
  5. 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)