CI/CD pour monorepo React SPA : comment automatiser les tests et déployer uniquement ce qui a changé
La plupart des articles sur les monorepos s’arrêtent à la structure des dossiers. Ils vous montrent comment organiser les applications et les packages, ajoutent peut-être une configuration partagée, et considèrent que c’est terminé. Mais la structure des dossiers n’est pas ce qui rend un monorepo prêt pour la production. Ce qui compte réellement, c’est de savoir si votre pipeline CI/CD peut détecter ce qui a changé, exécuter les bonnes portes de validation et déployer uniquement les applications qui doivent être mises à jour.
C’est la différence entre un monorepo qui a l’air propre et un monorepo qui livre de manière fiable. Le dépôt react-spa-monorepo-cicd est construit autour de cette distinction. C’est une architecture de référence avec 7 portes de validation, une détection intelligente des changements, une couverture E2E Playwright, des branches staging et production, et un rollback automatisé via SSH et rsync. Cet article explique pourquoi chacun de ces éléments est important et comment ils s’assemblent dans un système de livraison qui passe à l’échelle.
Pourquoi le CI/CD est la vraie valeur d’un monorepo SPA
Un monorepo en lui-même ne réduit pas le risque de déploiement. Mettre trois applications dans un seul dépôt sans automatisation partagée, c’est juste un dossier partagé avec des conflits de merge en plus. Le vrai bénéfice vient d’une validation cohérente, d’une automatisation partagée et d’un déploiement sélectif — rien de tout cela n’arrive automatiquement parce que vos applications partagent un package.json racine.
Le pipeline compte plus que l’arborescence des dossiers. Un monorepo avec un CI/CD solide donne à chaque application les mêmes standards de validation, le même chemin de déploiement et le même processus de rollback. Un monorepo sans CI/CD vous donne trois applications plus difficiles à livrer indépendamment que si elles vivaient dans des dépôts séparés.
C’est pourquoi le dépôt react-spa-monorepo-cicd est positionné comme une architecture de référence pour plusieurs applications avec déploiement automatisé et validation CI/CD complète, et non comme un simple template de démarrage. La valeur réside dans le système de livraison, pas dans la disposition de l’espace de travail.
Comment le pipeline fonctionne de la pull request à la production
Le chemin de livraison suit un modèle de promotion linéaire avec validation à chaque étape :
- Ouvrir une pull request — le CI détecte quelles zones ont changé et exécute la suite de validation complète
- Merger vers staging — les mêmes vérifications s’exécutent à nouveau sur le résultat du merge, puis les applications concernées sont déployées dans l’environnement de staging
- Vérifier le staging — des tests de fumée manuels ou automatisés confirment que le déploiement est sain
- Merger staging vers main — la validation s’exécute à nouveau, et les applications concernées sont déployées en production
- Vérifications post-déploiement — le pipeline confirme que chaque application déployée répond correctement
Les tests sont intentionnellement ré-exécutés après le merge. Une pull request valide la branche de manière isolée, mais l’état après merge peut différer en raison de conflits ou de changements simultanés. La validation post-merge garantit que le code exactement mergé passe encore toutes les portes avant tout déploiement.
C’est plus sûr que de déployer directement depuis les branches de fonctionnalité, car chaque déploiement en production a été validé au moins trois fois : sur la PR, après le merge vers staging et après le merge vers main. Chaque validation détecte une catégorie différente de problèmes.
Les sept portes de validation qui protègent chaque déploiement
Le pipeline impose sept catégories de vérifications avant tout déploiement, ordonnées de la moins coûteuse à la plus coûteuse :
- Vérification du format — Prettier détecte les incohérences de style en quelques secondes
- Lint — ESLint signale les problèmes de qualité de code et les bugs potentiels
- Vérification des types — Le compilateur TypeScript vérifie la correction à travers tous les packages
- Tests unitaires — Vitest exécute des tests rapides et isolés pour les composants et utilitaires
- Build — Vite compile chaque application en assets statiques prêts pour la production
- Audit de sécurité — L’analyse des dépendances signale les vulnérabilités connues
- Tests E2E — Playwright exécute des tests au niveau du navigateur contre les applications compilées
L’ordre est délibéré. Les vérifications de format et de lint ne coûtent presque rien à exécuter. Si elles échouent, il n’y a aucune raison de passer du temps à compiler trois applications et à lancer une stack Docker pour les tests E2E. Échouer tôt sur les vérifications bon marché permet de ne dépenser des ressources sur les vérifications coûteuses que lorsque les bases sont déjà propres.
C’est le même principe d’échec rapide qui rend tout pipeline CI efficace. La différence est que ce dépôt l’applique de manière cohérente à travers un monorepo avec plusieurs applications déployables, ce qui signifie que les économies se cumulent. Si une erreur de lint dans l’admin SPA fait échouer le pipeline en 15 secondes, vous évitez des minutes de builds, d’analyses de sécurité et de tests navigateur inutiles pour les deux SPA et le site principal.
Pourquoi les déploiements sélectifs sont le plus grand atout du monorepo
Sans détection des changements, chaque push reconstruit et redéploie chaque application. Cela gaspille du calcul, ralentit le feedback et augmente le rayon d’impact de chaque livraison. Un bug dans l’admin SPA ne devrait pas nécessiter le redéploiement du portail SPA et du site marketing.
Le dépôt utilise la détection intelligente des changements pour mapper les modifications de fichiers aux cibles de déploiement :
- Les changements dans
apps/admin-spa/déploient uniquement l’admin SPA - Les changements dans
apps/portal-spa/déploient uniquement le portail SPA - Les changements dans
apps/main-site/déploient uniquement le site principal (un site HTML statique, pas un React SPA) - Les changements dans
packages/déclenchent le déploiement des deux SPA car le code partagé pourrait affecter l’un ou l’autre consommateur - Les changements dans la documentation ou le markdown uniquement sautent le déploiement
Cela affecte directement trois choses qui importent aux équipes : le coût CI, la vitesse de feedback et le risque de livraison. Compiler et déployer une application au lieu de trois réduit le temps de calcul proportionnellement. Un pipeline ciblé se termine plus vite, ce qui signifie des cycles de revue de code plus rapides. Et déployer uniquement l’application modifiée réduit la surface exposée aux régressions dans du code non lié.
Le déploiement sélectif est là où les monorepos justifient leur existence. Sans lui, les monorepos deviennent rapidement lents et coûteux à mesure que le nombre d’applications croît. Avec lui, ajouter une nouvelle application au dépôt ne ralentit pas les déploiements des autres applications.
Où Playwright s’inscrit dans un processus sérieux de livraison frontend
Les tests E2E constituent la dernière couche de confiance avant le déploiement. Ils valident le comportement déployable dans un environnement proche de la production, ce qui est fondamentalement différent des tests unitaires exécutant des composants isolés.
Le dépôt exécute les tests Playwright contre des artefacts compilés servis par Docker et nginx, pas contre un serveur de développement. Cette distinction est importante car les serveurs de développement utilisent le remplacement de module à chaud, sautent des optimisations et servent les assets différemment. Exécuter les E2E contre la sortie de build de production détecte des problèmes qui n’apparaissent que dans des conditions réelles de déploiement.
La suite E2E couvre :
- Chargement de l’application — chaque SPA rend son composant racine
- Limites de routage — le routage côté client fonctionne au sein de chaque application
- Navigation inter-applications — les liens entre les SPA se résolvent sans erreur
- Régression visuelle — les captures d’écran sont comparées aux références pour détecter les changements d’interface non intentionnels
- Accessibilité — les vérifications axe-core signalent les violations critiques avant le déploiement
C’est de la confiance au niveau du pipeline, pas du débogage au niveau du développeur. Les tests E2E ne doivent pas remplacer les tests unitaires. Ils doivent répondre à une question différente : « L’artefact compilé fonctionne-t-il correctement lorsqu’il est servi comme la production le servira ? » Si la réponse est non, le déploiement n’a pas lieu.
Pourquoi staging et production doivent se comporter différemment
Le dépôt sépare les environnements par branche. Les pushes vers staging compilent en mode staging, utilisent les secrets de staging et déploient sur le serveur de staging. Les pushes vers main compilent en mode production, utilisent les secrets de production et déploient sur le serveur de production. Aucun code applicatif ne change entre les environnements — seuls le mode de compilation, les secrets et la cible de déploiement diffèrent.
Le staging n’est pas un environnement de démonstration. C’est une couche de confiance. L’objectif du staging est de détecter les problèmes qui n’apparaissent que dans un environnement déployé — mauvaises variables d’environnement, configuration serveur cassée, assets obsolètes — avant que ces problèmes n’atteignent les clients.
Les déploiements en production peuvent nécessiter une approbation manuelle via les règles de protection d’environnement GitHub. Après que la validation est passée, le job de déploiement se met en pause et attend qu’un membre autorisé de l’équipe approuve la mise en production. C’est de l’automatisation contrôlée : le pipeline gère la mécanique, les humains gèrent le jugement. Entièrement automatisé ne signifie pas nécessairement entièrement sans révision.
Le modèle de déploiement : rsync, sauvegardes et rollback
Le dépôt déploie en utilisant rsync via SSH. Chaque application a son propre chemin cible sur le serveur, donc déployer l’admin SPA ne risque pas d’écraser les fichiers du portail SPA. Les scripts de déploiement supportent le mode dry-run pour que vous puissiez vérifier l’intention avant de transférer les fichiers.
Avant chaque déploiement, le pipeline crée une sauvegarde horodatée de la version actuelle. Si un déploiement introduit un problème, le rollback se fait en une seule commande qui restaure la sauvegarde la plus récente. Ce n’est pas une réflexion d’urgence de dernière minute — cela fait partie de la conception de la livraison.
Les vérifications de santé post-déploiement ferment la boucle. Un transfert de fichiers réussi ne garantit pas une application fonctionnelle. La configuration du serveur pourrait être incorrecte, les variables d’environnement pourraient manquer, ou le build pourrait avoir été créé avec le mauvais mode. Les vérifications de santé confirment que l’application déployée répond réellement, et si elles échouent, le pipeline rapporte un échec même si le déploiement lui-même a réussi.
Des mécanismes de déploiement simples sont souvent plus maintenables qu’une complexité de plateforme surdimensionnée. Rsync, SSH et les sauvegardes horodatées sont des technologies ennuyeuses, mais elles sont prévisibles, débuggables et comprises par chaque ingénieur ops de l’équipe.
Si vous pensez également à sécuriser ce qui transite par votre pipeline, consultez La sécurité de la chaîne d’approvisionnement logicielle à l’ère de l’IA pour les stratégies d’intégrité des dépendances et de SBOM, et Sécuriser les workflows des agents de codage IA pour le sandboxing et les portes de révision lorsque du code généré par l’IA entre dans les pull requests d’un monorepo.
GitHub Actions et GitLab CI dans le même monorepo
Le dépôt inclut à la fois .github/workflows/validate-and-deploy.yml et .gitlab-ci.yml avec une documentation de configuration pour chacun. Supporter les deux est utile pour les équipes qui migrent entre plateformes, qui servent différents clients, ou qui évaluent quel système CI correspond le mieux à leur workflow.
Le point le plus important est que le pattern CI/CD compte plus que le fournisseur. La même échelle de validation, la même logique de déploiement sélectif et le même modèle d’environnement basé sur les branches fonctionnent dans les deux systèmes. La syntaxe d’implémentation diffère, mais l’architecture est portable. Si vous comprenez le pattern, vous pouvez l’implémenter dans n’importe quel système CI.
Ce que les équipes font généralement mal avec le CI/CD monorepo
Les erreurs les plus courantes ne sont pas des échecs techniques. Ce sont des omissions architecturales :
- Traiter la structure des dossiers comme la solution complète. Un workspace propre ne vous protège pas des merges cassés ou des minutes CI gaspillées.
- Ignorer la détection des changements. Sans elle, chaque push reconstruit tout, ce qui élimine l’avantage de vitesse d’un monorepo.
- Exécuter les E2E trop tôt ou trop tard. Les E2E avant le build gaspillent du temps sur des tests qui ne peuvent pas s’exécuter. Les E2E après le déploiement signifient que les échecs atteignent un environnement avant d’être détectés.
- Déployer tout à chaque merge. Cela transforme chaque livraison en un événement full-stack indépendamment de ce qui a réellement changé.
- N’avoir aucun plan de rollback. Si votre seule option de récupération est « pousser un correctif en avant », vous êtes à un mauvais déploiement d’un temps d’arrêt prolongé.
- Mélanger le comportement staging et production. Si le staging se déploie automatiquement mais la production aussi, le staging ne sert en réalité de porte pour rien.
La plupart de ces problèmes sont résolus en concevant le pipeline intentionnellement plutôt qu’en le laissant évoluer organiquement. Le dépôt react-spa-monorepo-cicd existe spécifiquement pour montrer à quoi ressemble un pipeline intentionnel.
À qui cette configuration convient-elle le mieux
Cette architecture convient aux équipes qui gèrent plusieurs SPA ou un mélange d’applications statiques et SPA depuis un seul dépôt. Cela inclut :
- Les équipes produit qui gèrent des applications séparées destinées aux utilisateurs et partageant des design systems ou des clients API
- Les agences qui construisent et maintiennent plusieurs surfaces frontend pour leurs clients
- Les équipes de plateforme interne avec des packages partagés consommés par plusieurs applications
- Les développeurs qui veulent un CI/CD simple mais capable de production sans adopter un framework monorepo lourd
Si vous utilisez déjà Nx ou Turborepo et êtes satisfait de la complexité, cette approche peut sembler trop manuelle. Mais si vous voulez comprendre ce que ces outils abstrahent, ou si vous voulez une alternative plus légère que vous contrôlez entièrement, c’est un excellent point de départ.
Que faire ensuite
Si vous voulez implémenter ce pipeline de manière pratique, suivez le tutoriel compagnon : Comment configurer le CI/CD et les tests automatisés pour un monorepo React SPA. Il vous guide à travers chaque étape, du clonage du dépôt à la configuration des portes de validation, en passant par l’exécution des tests E2E Playwright, la mise en place des déploiements sélectifs et la configuration des livraisons staging et production.
Pour les équipes qui exécutent déjà des pipelines CI/CD, envisagez de mapper les patterns de cet article à votre configuration existante :
- Ajoutez la détection des changements si vous reconstruisez tout à chaque push
- Ordonnez vos portes de validation de la moins coûteuse à la plus coûteuse
- Séparez staging de la production avec des règles d’environnement basées sur les branches
- Ajoutez des vérifications de santé post-déploiement pour qu’un transfert réussi ne termine pas l’histoire
- Intégrez le rollback dans le pipeline au lieu de le traiter comme une procédure d’urgence
Si vous voulez un point de départ plutôt qu’un document d’architecture vierge, ce dépôt vous en fournit un : un système de livraison monorepo avec des portes de validation, un déploiement sélectif, des tests E2E et un rollback déjà intégrés. La prochaine étape est d’adapter ces patterns à vos propres applications et cibles de déploiement au lieu de réinventer le CI/CD à partir de zéro.
Obtenir le dépôt react-spa-monorepo-cicd →
Suivre le tutoriel étape par étape →
Questions fréquentes
Quelle est la différence entre un monorepo et un polyrepo pour le CI/CD ?
Un monorepo conserve plusieurs applications et packages partagés dans un seul dépôt, ce qui permet des pipelines CI/CD partagés, une validation cohérente et un déploiement sélectif basé sur la détection des changements. Un polyrepo utilise des dépôts séparés par application, ce qui simplifie les pipelines par application mais nécessite plus de coordination pour les dépendances partagées et les tests inter-applications.
Comment fonctionne le déploiement sélectif dans un monorepo ?
Le déploiement sélectif utilise la détection des changements pour mapper les fichiers modifiés aux cibles de déploiement. Si seul le répertoire d’une application a changé, seule cette application est compilée et déployée. Les changements dans les packages partagés déclenchent les déploiements pour toutes les applications qui en dépendent. Cela réduit le coût CI, accélère le feedback et limite le rayon d’impact de chaque livraison.
Les tests E2E doivent-ils s’exécuter avant ou après le déploiement ?
Les tests E2E doivent s’exécuter avant le déploiement, contre des artefacts compilés servis dans un environnement proche de la production. Cela détecte les problèmes d’intégration et de déploiement avant qu’ils n’atteignent le staging ou la production. Les vérifications de santé post-déploiement confirment ensuite que l’application réellement déployée répond correctement.
Puis-je utiliser ce pattern CI/CD avec Nx ou Turborepo ?
Oui. L’échelle de validation, la logique de déploiement sélectif et le modèle d’environnement basé sur les branches sont des patterns d’architecture, pas des configurations spécifiques à un outil. Si vous utilisez déjà Nx ou Turborepo pour l’orchestration des tâches et la mise en cache, vous pouvez superposer ces patterns CI/CD par-dessus. Le dépôt react-spa-monorepo-cicd démontre les patterns sans framework lourd afin que vous puissiez voir exactement ce que ces outils abstrahent.
Comment ajouter une nouvelle application au pipeline du monorepo ?
Créez l’application sous apps/, ajoutez son répertoire au script de détection des changements (scripts/changed-files.sh) et connectez les cibles de build, déploiement et E2E correspondantes dans le workflow CI. Le modèle de déploiement sélectif évolue linéairement — chaque nouvelle application obtient son propre chemin conditionnel sans ralentir les déploiements des applications existantes.
Comment cette approche gère-t-elle les changements de packages partagés ?
Les changements sous packages/ déclenchent des reconstructions et des déploiements pour toutes les applications qui dépendent de ces packages partagés. C’est intentionnel — un bug dans le code partagé pourrait casser n’importe quel consommateur, donc chaque application dépendante doit être reconstruite, retestée et redéployée pour détecter les régressions.