CaenHackYouAcademy
DevSecOps

Architectures de pipelines

Monorepo, multi-dépôts, matrices : structurer à l'échelle.

Une startup de trois personnes avec un seul service n'a pas besoin de la même architecture qu'une banque de deux cents équipes et de centaines de microservices. La première se pilote avec une pipeline unique qui construit, teste et déploie la seconde doit découper ses dépôts, détecter les changements et coordonner des dizaines de chaînes. Il n'existe pas de « meilleure » pipeline — seulement celle qui correspond à votre contexte.

En bref

Parler d'architecture de pipeline, c'est parler de la façon dont on organise l'ensemble des pipelines, pas du contenu de l'une d'elles : combien y en a-t-il, comment se déclenchent-elles, et comment les artefacts circulent-ils entre elles ?

Trois facteurs qui décident

FacteurQuestions à se poser
Structure d'équipecombien de développeurs, combien d'équipes ? travaillent-elles sur le même code ?
Stratégie de branchesplusieurs branches longues, ou tout le monde sur main ?
Modèle de déploiementune fois par mois ou cinquante fois par jour ? plusieurs versions en production ?

L'architecture n'est pas un choix esthétique : elle découle de ces trois réponses.

Stratégies de branches

La façon dont vous organisez vos branches Git détermine directement la structure de vos pipelines. Deux philosophies s'opposent.

À gauche, des branches qui vivent des semaines à droite, des branches qui vivent une matinée.

Pipeline par branche

Plusieurs branches « longues » vivent en parallèle pendant des semaines. Les développeurs travaillent sur des branches feature/*, fusionnées dans develop une release/X.Y est ouverte pour préparer une version, puis fusionnée dans main après validation. Chaque branche longue a sa propre pipeline.

BrancheCe que fait la pipeline
feature/*tests unitaires, style, analyse statique
developtests, puis déploiement en environnement de développement
release/*tests complets, déploiement en staging, tests d'acceptation
maindéploiement en production, souvent après approbation

Une branche, un rôle, un comportement de pipeline.

Les avantages tiennent en trois mots : séparation claire — un environnement par branche, facile à expliquer —, contrôle fin sur ce qui part en production et quand, et versions parallèles maintenables (1.0, 1.1, 2.0). En face : la complexité de plusieurs pipelines qui peuvent diverger, des fusions douloureuses — plus une branche vit longtemps, plus les conflits s'accumulent — et un délai de plusieurs semaines entre l'écriture du code et sa mise en production.

Contexte idéal

Équipes à cycles de publication planifiés — mensuels, trimestriels — et produits dont plusieurs versions cohabitent chez les clients : logiciels installés, applications mobiles.

Trunk-based : tout sur une seule branche

Tout le monde travaille sur la branche principale. Les branches de fonctionnalité existent mais durent quelques heures, rarement plus d'une journée : on ouvre une demande de fusion, elle est revue rapidement, et dès la fusion la pipeline se déclenche. Si tout passe, le code peut partir en production automatiquement.

{Le drapeau de fonctionnalité : du code en production, mais éteint.}
if feature_flags.is_enabled("nouvelle_interface_paiement"):
    afficher_nouvelle_interface()
else:
    afficher_ancienne_interface()

C'est la clé du modèle : comment déployer du code qui n'est pas terminé ? En le déployant désactivé. Quand la fonctionnalité est prête, on l'active pour quelques utilisateurs, puis pour tous.

Les avantages : une intégration réellement continue — le code est intégré plusieurs fois par jour —, pas d'enfer des fusions puisque les branches sont courtes, et un retour rapide sur la compatibilité avec le travail des autres. Le prix : une discipline stricte — chaque commit sur main doit être de qualité production —, des drapeaux de fonctionnalité obligatoires, donc une infrastructure de plus à gérer, et une couverture de tests excellente sans laquelle c'est le chaos.

Contexte idéal

Équipes matures pratiquant le déploiement continu, produits en ligne où une seule version est en production.

Laquelle choisir

AspectPipeline par brancheTrunk-based
Fréquence de fusionjours ou semainesheures
Nombre de pipelinesune par type de brancheune seule
Drapeaux de fonctionnalitéoptionnelsobligatoires
Risque de conflit Gitélevé : branches longuesfaible : branches courtes
Délai jusqu'à la productionjours ou semainesminutes ou heures
Complexité de la pipelinemoyenne à élevéesimple
Besoin en testsimportantcritique

La ligne décisive est la première : la fréquence de fusion détermine tout le reste.

Le raccourci de décision : une livraison par mois ou moins, GitFlow reste acceptable plusieurs par semaine, le trunk-based mérite considération plusieurs versions en production, GitFlow est souvent nécessaire un service en ligne à version unique, le trunk-based est plus adapté.

Monorepo ou polyrepo

Autre question structurante : combien de dépôts Git avez-vous ?

Monorepo : tout dans un seul dépôt

Tous les services, bibliothèques et outils partagent le même dépôt. Google, Meta et Microsoft emploient cette approche pour une grande partie de leur code.

monorepo/
├── services/
│   ├── api/           service backend
│   ├── frontend/      application web
│   └── worker/        traitement asynchrone
├── libs/
│   ├── auth/          bibliothèque d'authentification
│   └── utils/         utilitaires partagés
└── infra/
    ├── terraform/     infrastructure décrite en code
    └── k8s/           manifestes Kubernetes

Le défi : ne pas tout reconstruire à chaque commit. Si quelqu'un modifie le fichier d'aide du frontend, il est inutile de reconstruire l'API — la pipeline doit détecter ce qui a réellement changé.

Commit modifiant : services/api/src/users.py

Analyse des dépendances :
  services/api        -> reconstruire  (fichier modifié)
  libs/auth           -> vérifier      (l'API l'utilise peut-être)
  services/frontend   -> ignorer       (non impacté)
  services/worker     -> ignorer       (non impacté)

Avantages : refactorisation atomique — une seule demande de fusion modifie l'API, le frontend et les bibliothèques en restant cohérente —, partage de code naturel sans publication de paquets, et cohérence des versions. Inconvénients : une pipeline complexe, qui exige un outillage de détection des changements, un temps de clonage qui grandit avec le dépôt, et des permissions difficiles à restreindre partie par partie.

OutilÉcosystèmePoint fort
NxJavaScript, TypeScriptexcellent sur les projets frontend
TurborepoJavaScript, TypeScriptsimple, rapide, cache distribué
Bazelpolyglottetrès puissant, apprentissage exigeant
PantsPython, Go, Javabonne alternative à Bazel

Quatre outils de construction incrémentale — le monorepo sans outillage ne tient pas à l'échelle.

Polyrepo : un dépôt par service

github.com/acme/api          dépôt et pipeline propres
github.com/acme/frontend     idem
github.com/acme/worker       idem
github.com/acme/libs-auth    publié comme paquet (npm, PyPI…)
github.com/acme/infra        Terraform séparé

Avantages : une pipeline simple par dépôt, des équipes autonomes — l'équipe API déploie sans attendre le frontend — et des permissions claires. Inconvénients : la coordination des versions (l'API v2.3 est-elle compatible avec le frontend v1.8 ?), la duplication des configurations de pipeline d'un dépôt à l'autre, et une refactorisation pénible — modifier une interface partagée impose plusieurs demandes de fusion dans plusieurs dépôts.

L'enfer des dépendances

En polyrepo, les bibliothèques partagées sont publiées comme des paquets. Trois questions apparaissent aussitôt : quand libs-auth publie une version, qui la met à jour dans chaque service ? Comment s'assurer que tous les services restent compatibles ? Que faire d'un service bloqué sur une vieille version ?

En pratique : une stratégie hybride

Peu d'organisations sont entièrement monorepo ou entièrement polyrepo. La plupart tranchent type de code par type de code.

Type de codeStratégiePourquoi
Services métiermonoreporefactorisation atomique, cohérence
Infrastructuredépôt séparécycle de vie et permissions distincts
Bibliothèques très partagéesdépôts séparés, versionnésréutilisation au-delà de l'organisation

Le découpage suit les cycles de vie, pas l'organigramme.

Promotion plutôt que reconstruction

L'artefact déployé en production est-il bien celui qui a été testé ? Le chapitre a posé le principe — construire une fois, déployer partout il vaut aussi à l'échelle de l'architecture : c'est la même image qui traverse dev, staging et production, seule la configuration change.

{L'approbation manuelle porte sur un artefact déjà construit et déjà testé.}
build:
  script:
    - docker build -t app:CI_COMMIT_SHA .
    - docker push registry/app:CI_COMMIT_SHA

staging:
  script:
    - helm upgrade app ./chart --set image.tag=CI_COMMIT_SHA
        --set env=staging -f values-staging.yaml

production:
  script:
    - helm upgrade app ./chart --set image.tag=CI_COMMIT_SHA
        --set env=production -f values-production.yaml
  when: manual        # approbation requise

Trois prérequis, du côté de l'application : séparer la construction de la configuration — aucune URL ni identifiant en dur —, accepter sa configuration à l'exécution, et disposer d'un registre d'artefacts fiable où stocker les images entre les étapes.

Pipeline applicative et pipeline d'infrastructure

L'infrastructure aussi peut — et devrait — être pilotée par une pipeline. Mais les deux n'ont ni la même fréquence ni le même rayon d'impact, et c'est cette asymétrie qui justifie de les traiter séparément.

Pipeline applicativePipeline d'infrastructure
Ce qu'elle déploiele code : API, frontend, workers, tâches planifiéesles ressources : réseaux, bases de données, clusters, DNS
Déclencheurun commit sur le code applicatifune modification de l'infrastructure décrite en code
Fréquenceélevée, plusieurs fois par jourfaible, quelques fois par semaine
Impactlimité, un service à la foislarge, potentiellement tous les services

Deux rythmes, deux rayons d'impact — donc deux régimes de garde-fous.

ApprocheAvantagesInconvénients
Pipelines séparéescycles indépendants, permissions distinctes, rayon d'impact limitécoordination parfois manuelle
Pipeline uniquedéploiement atomique de l'infrastructure et de l'applicationcomplexité, risque élevé en cas d'échec

Recommandation : séparer, mais coordonner.

Mélanger les deux produit des pipelines lourdes, où un changement de couleur de bouton déclenche une vérification Terraform. Trois façons de coordonner sans fusionner : des déclencheurs — la pipeline d'infrastructure lance l'applicative après succès —, le GitOps — un opérateur comme ArgoCD ou Flux détecte les changements et déploie — ou des dépendances explicites, l'applicative vérifiant que l'infrastructure est à jour avant de déployer.

Trois formes avancées

La pipeline en diamant

Exécuter un maximum de jobs en parallèle, puis reconverger avant l'étape suivante. Le graphe en prend la forme : un point de départ, une divergence, une convergence, puis à nouveau.

Un diamant : trois vérifications en parallèle, une convergence avant la construction.

Le temps total baisse, le retour arrive plus tôt — un échec de style se voit sans attendre la fin des tests — et les runners travaillent en parallèle. Revers : tous les jobs parallèles doivent réussir pour passer à la suite un seul échec bloque la convergence.

La matrice

Votre bibliothèque doit fonctionner avec Python 3.9 à 3.12, sur Ubuntu, macOS et Windows : douze combinaisons. La matrice les engendre automatiquement.

{Quatre versions fois trois systèmes : douze jobs parallèles, quatre lignes de configuration.}
test:
  strategy:
    matrix:
      python: [3.9, 3.10, 3.11, 3.12]
      os: [ubuntu-24.04, macos-latest, windows-latest]

Cas d'usage : bibliothèques ouvertes à compatibilité large, applications de bureau multi-systèmes, validation de compatibilité avant une montée de version.

La pipeline conditionnelle

ConditionComportement
branche maindéployer en staging, puis en production après approbation
branche feature/*déployer dans un environnement éphémère, détruit sous 24 h
fichiers modifiés dans docs/ignorer les tests, reconstruire seulement la documentation
tag créé (v*)publier une version et les paquets associés

Économie de ressources, retour adapté au contexte — sans multiplier les pipelines.

Choisir : quatre questions

Combien d'équipes travaillent sur le code ?

Le nombre d'équipes qui partagent le code décide surtout entre monorepo et polyrepo. Tant qu'une seule équipe touche à l'ensemble, un monorepo reste simple à outiller.

SituationRecommandation
une équipe, moins de 10 personnesmonorepo simple, trunk-based envisageable
deux à cinq équipesmonorepo outillé (Nx, Turborepo) ou polyrepo léger
dix équipes et pluspolyrepo probable, ou monorepo avec une équipe dédiée à l'outillage

Au-delà de quelques équipes, il faut investir dans l'outillage ou découper.

À quelle fréquence déployez-vous ?

Plus vous livrez souvent, moins les branches longues sont tenables : le coût des fusions finit par dépasser le contrôle qu'elles apportent.

FréquenceRecommandation
mensuelle ou moinsGitFlow acceptable, promotion d'artefact recommandée
hebdomadairetrunk-based à considérer, promotion obligatoire
quotidienne ou plustrunk-based, drapeaux de fonctionnalité, déploiement continu

À partir du rythme hebdomadaire, la promotion cesse d'être un confort.

Avez-vous plusieurs versions en production ?

C'est souvent la question la plus contraignante, car elle ne dépend pas de vos préférences mais de votre produit.

SituationRecommandation
non : service en ligne, version uniquetrunk-based, pipeline unique
oui : logiciel installé, application mobilebranches de publication, pipelines par branche

Un produit installé chez le client impose de maintenir plusieurs versions en parallèle.

Quelle est votre maturité en tests ?

Elle agit comme un garde-fou sur tout ce qui précède : le trunk-based et le déploiement continu ne fonctionnent que si les tests attrapent réellement les régressions. Sinon, chaque fusion devient un pari.

NiveauRecommandation
peu ou pas de tests automatiséspipelines simples, investir d'abord dans les tests
couverture correcte (plus de 60 %)trunk-based envisageable, avec prudence
excellente couverture et tests d'intégrationdéploiement continu possible

Accélérer les déploiements sans tests solides transforme la pipeline en distributeur d'incidents.

L'anti-patron : copier sans comprendre

« Netflix fait du trunk-based, on devrait faire pareil »

Netflix a des centaines d'ingénieurs dédiés à l'outillage, des années d'itération sur ses pratiques, une infrastructure de tests et de drapeaux de fonctionnalité mature, et un contexte de service en ligne à version unique. Copier l'architecture sans reproduire ces quatre conditions, c'est hériter de la complexité sans le socle qui la rend soutenable : pipelines fragiles, déploiements ratés, et une équipe qui répare l'outillage au lieu de livrer.

La bonne approche

  1. Commencer simple — une pipeline linéaire qui construit, teste, déploie.
  2. Identifier les douleurs — qu'est-ce qui vous ralentit réellement ?
  3. Évoluer progressivement — ajouter de la complexité quand le besoin est démontré.
  4. Mesurer — durée de pipeline, fréquence de déploiement, taux d'échec.

À retenir de cette séance

L'architecture de pipeline reflète votre contexte — structure d'équipe, stratégie de branches, modèle de déploiement — et il n'existe pas de solution universelle. Trunk-based ou GitFlow : branches courtes, moins de conflits et un retour rapide, mais discipline et drapeaux de fonctionnalité branches longues, plus de contrôle, mais fusions douloureuses. Monorepo ou polyrepo : le premier facilite refactorisation et cohérence mais demande de l'outillage le second donne de l'autonomie mais complique la coordination. Promotion plutôt que reconstruction. Application et infrastructure séparées, mais coordonnées. Et surtout : commencer simple, complexifier quand c'est nécessaire.

VérificationQuestion 1 / 3

Réponse unique

Quel est le principal coût du développement sur tronc commun ?

Indice · Comment intégrer souvent du travail pas encore terminé ?

On this page