Monorepo avec Go : organisation du code pour des projets évolutifs
Dans le développement logiciel moderne, la question se pose de plus en plus : comment organiser le code pour qu'il reste gérable, réutilisable et évolutif ? L'une des solutions populaires est l'utilisation d'un monorepo — un référentiel unique contenant plusieurs projets ou services. Dans cet article, nous allons voir comment organiser efficacement un monorepo en langage Go (Golang), examiner les meilleures pratiques, la structure des répertoires, le travail avec les modules et la configuration CI/CD.
Qu'est-ce qu'un monorepo et pourquoi en a-t-on besoin en Go ?
Un monorepo est une approche où tout le code d'une entreprise ou d'un grand projet est stocké dans un seul référentiel. Cela peut inclure :
- Plusieurs microservices
- Des bibliothèques et des utilitaires
- Des configurations et des scripts
- De la documentation
Avantages du monorepo pour Go :
- Version unique des dépendances — élimine les conflits de versions entre les services.
- Simplification du refactoring — les modifications dans une bibliothèque commune sont immédiatement visibles par tous les consommateurs.
- Réutilisation facile du code — pas besoin de publier les packages dans un registre.
- Historique unique des commits — simplifie le débogage et l'audit.
Cependant, un monorepo exige de la discipline : sans une structure claire, il se transforme rapidement en "dépotoir". Go, avec son système strict de modules (Go Modules), offre d'excellents outils pour organiser un tel référentiel.
Structure des répertoires dans un monorepo Go
Une structure correcte est la clé du succès. Examinons l'organisation recommandée pour un monorepo en Go :
my-monorepo/├── apps/ # Applications (services, utilitaires CLI)│ ├── api-gateway/│ │ ├── cmd/│ │ │ └── main.go│ │ ├── internal/│ │ ├── go.mod│ │ └── go.sum│ ├── auth-service/│ │ └── ...│ └── user-service/│ └── ...├── libs/ # Bibliothèques communes│ ├── common/│ │ ├── logger.go│ │ ├── config.go│ │ ├── go.mod│ │ └── go.sum│ └── models/│ ├── user.go│ ├── go.mod│ └── go.sum├── scripts/ # Scripts de build, de déploiement│ ├── build.sh│ └── deploy.sh├── docs/ # Documentation├── .github/ # Configurations CI/CD│ └── workflows/│ └── ci.yml├── go.work # Fichier Workspace (Go 1.18+)├── Makefile # Commandes communes├── README.md└── .gitignoreÉléments clés de la structure :
- apps/ — contient les applications exécutables (services, utilitaires). Chaque application est un module Go distinct avec son propre
go.mod. - libs/ — bibliothèques communes réutilisées entre les applications.
- go.work — fichier workspace permettant de travailler avec tous les modules localement sans publier les modifications.
Travailler avec Go Modules dans un monorepo
À partir de Go 1.18, la prise en charge des workspaces (go.work) est apparue. Cela résout le problème du développement local lorsque les modules dépendent les uns des autres. Examinons un exemple de configuration.
Créons un fichier go.work à la racine du monorepo :
go 1.21
use ( ./apps/api-gateway ./apps/auth-service ./libs/common ./libs/models)Désormais, lors du développement local, Go utilisera les versions locales des modules, et non les versions publiées. C'est crucial pour une itération rapide.
Exemple de dépendance dans apps/auth-service/go.mod :
module github.com/company/auth-service
go 1.21
require ( github.com/company/libs/common v0.0.0 github.com/company/libs/model