Maximize Page
Tech & DevOps HubEspace Tech & DevOps: Explorez le monde du Dev, du Cloud et des outils DevOps à travers nos articles et discussions Explore the world of development, the cloud and DevOps tools

Les profils Spring: Préparation au multibranche

Date de l'article:18-10-2025
Github-Actions Spring Boot
Mise en place de trois profils Spring Boot distincts (dev, staging, prod) avec une configuration de base de données adaptée à chaque environnement. Préparation de l'application à la stratégie multi-branches du pipeline CI/CD avec les principes Gitlab flow
Cet article présente la mise en place des profils Spring, la configuration des bases de données suivant leurs besoins, l'ajout et/ou la mise à disposition de jeux de données associés, ainsi que la gestion des configurations par environnement. Nous adapterons également les paramètres pour les tests unitaires et d'intégration.
Pourquoi utiliser des profils Spring Boot ?
Chaque environnement ayant des besoins spécifiques, il nous faut adapter l'application à son contexte, par exemple en utilisant une base de données embarquée en développement et une base externe en production. L'idée est d'éviter d'avoir une seule configuration globale qui risque d'effacer des données ou d'exposer des informations sensibles.
Définition des bases de données selon le profil, la branche et les besoins de l'environnement:
Profil Branche Objectif / Besoin Type de DB Port Caractéristiques
dev develop Développement local locale 8080 Utilise: ddl-auto=create-drop - spring.sql.init.mode=always
Les données sont recréée à chaque lancement de l'application, les logs sont détaillés
staging staging Préproduction / tests persistante (VM/Docker) 8081 Utilise: ddl-auto=update - spring.sql.init.mode=never
Base persistante: Les données sont conservées (init manuelle), les logs modérés.
prod main Production finale distante (prod/CI) 8080 Utilise: ddl-auto=update - spring.sql.init.mode=never
Base stable; Les données ne jamais modifiées automatiquement, les logs sont limités;

En entreprise, la base de staging est souvent une copie anonymisée de la base de production pour tester en conditions réelles.


Structure typique des fichiers de configuration
Dans un projet Spring Boot, nous configurons ces besoins dans le dossier "src/main/resources"
Chaque environnement dispose de sa propre branche Git, et chaque branche a des besoins spécifiques.
Tous les fichiers sont présents dans toutes les branches.
Le fichier application.properties est la configuration commune à tous les environnements:
  • Il est utilisé pour la gestion centralisée de la configuration, comme paramétrer la base de données, le port, les healthchecks, etc
  • Il contient des paires de "clé=valeur" pour configurer l'application, permettant de modifier son comportement sans toucher au code
  • Il facilite la modification des paramètres par défaut de Spring Boot et offre une grande flexibilité pour les différents environnements
  • Il est surchargé par les fichiers de profils
Les fichiers de profils:
Ils sont essentiels pour gérer des configurations différentes selon l'environnement, en activant ou désactivant des propriétés et des composants spécifiques, ce qui offre flexibilité, maintenabilité et déploiement simplifié sans modifier le code principal
  • application-dev.properties: configuration locale et en dev
  • application-staging.properties: utilisé seulement en staging
  • application-prod.properties: utilisé en production
Le code et les fichiers de configuration restent identiques entre les branches;
Seules les valeurs externes, injectées par le pipeline (secrets, URLs de serveurs), varient d'un environnement à l'autre
     Des valeurs par défaut sont prévues uniquement pour le développement local.

Configuration des fichiers suivant les besoins des profils
Structure des fichiers
FLASHCARDS/
├── src/main/resources/
│   ├─ application.properties
│   ├─ application-dev.properties
│   ├─ application-staging.properties
│   └─ application-prod.properties
Fichiers de données sql, par branche
FLASHCARDS/
├── src/main/resources/db/dev/init-data.sql   ← données de develop
├── db/prod/init-data.sql                     ← données de prod
└── db/staging/init-data.sql                  ← données de staging
En dev: Les données sont auto-loadé à chaque démarrage de l'application
En staging/prod: insérer les données manuellement via la commande psql -h [host] -U postgres -d flashcardsdb -f db/[profile]/init-data.sql
Le mot de passe se trouve dans le fichier src/main/resources/application.properties

Le fichier "application.properties"
spring.application.name=flashcards
spring.jpa.open-in-view=false
spring.jpa.show-sql=false

spring.profils.default=dev

→ Contient le profil "dev" par défaut, ce qui empêche l'application de démarrer sans configuration explicite, réduisant ainsi les risques d'erreurs en offrant une configuration de base.
# PostgreSQL (all)
spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/flashcardsdb
spring.datasource.username=${DB_USER:postgres}
spring.datasource.password=${DB_PASSWORD:pswd}
spring.datasource.driver-class-name=org.postgresql.Driver
Le profil "dev" s'active automatiquement si aucun autre profil n'est spécifié lors du lancement de l'application:
# output
No active profile set, falling back to 1 default profile: "dev"

La configuration de ce fichier sera surchargée par les fichiers de profil pour en faire des configurations distinctes par branche.
Les avantages sont le découplage qui sépare la configuration de la logique métier.
Normalement on ne configure pas la base de données dans le fichier commun, mais bien dans les fichiers de profils
Ma décision de la mettre là est uniquement pour éviter la duplication (projet démo).
En temps normal: 1 base de données + credentials différent par branche/environnement!

1. Le profil "dev"
# application-dev.properties
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

spring.sql.init.mode=always
spring.sql.init.data-locations=classpath:db/dev/init-data.sql
spring.jpa.defer-datasource-initialization=true

# log level
logging.level.org.springframework.security=INFO

# default port
server.port=8080
Objectifs:
Faciliter les tests rapides, disposer du rechargement des données à chaque démmarage, et disposer de logs détaillés.
Comportements attendus:
→ La base est créée, puis supprimée à l'arrêt
→ Il charge le script "init-data.sql" à chaque lancement de l'application.
→ Les logs SQL sont activés et configurables selon le niveau nécessaire:
     INFO WARN DEBUG

2. Le profil "staging"
# application-staging.properties
# Hibernate: do not destroy anything
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false
spring.sql.init.mode=never

# Different port
server.port=8081
Objectifs: Simuler la production, avec une base stable et des tests de charge
Comportements attendus:
→ Mise à jour du schéma sans supprimer les données
→ Pas de rechargement automatique de la table
→ Pas de log SQL
→ Port différent, pour faire tourner [develop] et [staging] côte à côte
→ Idéal pour les tests de performance et/ou via Postman/Newman

Changer de profil au démarrage (staging / prod)
Pour utiliser le profil staging ou prod alors que le profil "dev" est le profil défini par défaut, il faut "écraser" la configuration au démarrage de l'application.
Utilisez une variable d'environnement (Recommandé):
export SPRING_profils_ACTIVE=staging

./mvnw spring-boot:run
ou le profil, ou le fichier jar:
./mvnw spring-boot:run -Dspring-boot.run.profils=prod
#ou encore
java -jar target/flashcards-1.1.0.jar --spring.profils.active=prod
Pas d'initialisation de données au démarrage (staging / prod)
→ Pas de rechargement automatique de la table: Il faut l'initialiser une première fois avant de lancer l'application
→ Insérer les données manuellement depuis la commande: psql -h [host] -U postgres -d flashcardsdb -f db/{profile}/init-data.sql
→ Vous pouvez redéfinir le user et mot de passe (voir le readme) ou, utiliser ceux définis dans le dossier "src/main/resources/application.properties"

3. Le profil "prod"
# application-prod.properties
# Prod safe
spring.sql.init.mode=never
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false

server.port=${PORT:8080}
Objectifs:
Obtenir la stabilité, la sécurité et de bonnes performances.
Comportements attendus: → Pas de logs SQL
→ Il à été de mon choix d'utiliser "spring.jpa.hibernate.ddl-auto=update" au lieu de "validate" pour avoir (éventuellement) des données à disposition au démarrage.
Résumé des bonnes pratiques
  • Toujours séparer les profils: Ne jamais activer "dev" en production
  • Protéger les credentials: Utiliser les secrets GitHub,.env, ou Docker secrets
  • Base staging = clone anonymisé de la prod. Permet des tests réalistes sans risques
  • Tests automatisés par environnement. Chaque branche déclenche son propre workflow CI/CD

Les profils de tests
Ces profils sont utilisés exclusivement par les tests unitaires et d'intégration; ils ne disposent donc pas de branches dédiées.
Ils sont localisés dans le dossier "src/test/resources/".
FLASHCARDS/
├── src/
│   └─ test/java/com/example/flashcards/
│       ├─ controller/                    ← test unitaire
│       ├─ dto/
│       ├─ entity/                        ← test unitaire
│       ├─ integration/                   ← test it 
│       ├─ mapper/
│       ├─ service/
│       └─ resources/
│           ├─ application-it.properties    ← it profile
│           └─ application-test.properties  ← test profile 
Grâce aux annotations, les tests trouvent leurs configurations.
  • profile-test.application pour les tests unitaires
  • profile-it.application pour les tests d'intégration
Ils tournent dans toutes les branches et vérifient le bon état du code.

Le profil "test"
# application-test.properties
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true

spring.sql.init.mode=never
spring.liquibase.enabled=false
spring.flyway.enabled=false

Utilise une base éphémère (H2) au lieu de Postgres

Logs attendus:
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
      :: Spring Boot ::                (v3.5.4)

      //... main] c.e.f.i.CategoryControllerTest 
                  : The following 1 profile is active: "test"

Le profil "it"
# application-it.properties
# IT Behavior
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=false

# Migrations
spring.liquibase.enabled=false
spring.flyway.enabled=false

spring.sql.init.mode=never
Le fichier est configuré à minima, pour être utilisé, tantôt pas H2 (dev) et, par Postgres (local/staging/main)

Logs attendus:
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
      :: Spring Boot ::                (v3.5.4)

      //... main] c.e.f.i.CategoryIntegrationIT  
                    : The following 1 profile is active: "it"

La différence fondamentale entre les applis Java/Spring Boot (où les profils sont intégrés au framework) et des environnements comme PHP, où la gestion des environnements est plus manuelle et basée sur des configurations distinctes, des variables d'environnement et des branches de déploiement séparées plutôt que sur des profils logiques, offre la même souplesse que Spring Boot, mais avec un peu plus de gestion manuelle.
Dans l'article suivant, nous passerons à la création de la branche develop, où nous mettrons en place tous les éléments nécessaires à la CI de base.

Laissez-moi un commentaire

En postant un commentaire anonyme, vous adhérez automatiquement aux conditions d'utilisation du site.