Cet article explore l'intégration de Spotless, Checkstyle et SpotBugs dans un projet Java/Spring Boot afin d'améliorer durablement la qualité du code, depuis leur configuration Maven jusqu'à l'analyse des rapports et la gestion des erreurs, tout en adaptant les règles aux besoins du projet
| Outil | Type | Pour Qui | Rôles | Seuils CI (recommandés) |
|---|---|---|---|---|
| Spotless | Formatage | Dev & CI | Normalisation automatique du code | Échec si non-formaté |
| Checkstyle | Lint | Dev & CI | Respect des conventions de nommage, structure, Javadoc | 0 violations |
| SpotBugs | Analyse statique | Dev & CI | Détection des bugs logiques grave (boucle infinie, null) | 0 HIGH |
| SonarQube / SonarCloud | Analyse complète | Dev, CI, Management | Qualité et sécurité globale du code, dette technique, sécurité | Quality Gate ≥ 80% |
L'association de ces outils permet de construire une véritable barrière qualité, active à la fois en local et dans le pipeline CI
Ensemble, ils interviennent avant même les tests unitaires
Chaîne logique: Spotless (corrige) → Checkstyle (impose le style) → SpotBugs (détecte les bugs) → Les tests (valident le comportement) → Sonar
L'intégration dans Maven permet d'uniformiser le comportement entre les postes développeurs et le CI
<properties> //...
<spotless.plugin.version>2.43.0
</properties>
//...
<!-- Spotless -->
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.plugin.version}</version>
<configuration>
<java>
<googleJavaFormat/>
</java>
</configuration>
</plugin>
Spotless Assure un formatage homogène
Il répare automatiquement le code via la commande "spotless:apply"
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<configLocation>google_checks.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<linkXRef>false</linkXRef>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
pour la config personnalisée, voir la partie + bas: "Ajout de fichier custom et de suppression"<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.8.6</version>
<configuration>
<failOnError>true</failOnError>
</configuration>
</plugin>
SpotBugs effectue une analyse statique avancée.
Il Bloque le build si une anomalie (critique) est détectée
Checkstyle, en utilisation d'une configuration standard (Google ou Sun) effectue les vérification des conventions, contrôle de structure et détecte les mauvaises pratiques.
Il est exécuté dans la phase "verify"
./mvnw checkstyle:check
./mvnw spotbugs:check
Lors de la première exécution, il est fréquent d'obtenir un échec:
$ ./mvnw checkstyle:check
//download and install pour une première utilisation
[INFO] -----------------------< com.example:flashcards >---------------
[INFO]
[INFO] --- checkstyle:3.6.0:check (default-cli) @ flashcards ---
[INFO] There are 16 errors reported by Checkstyle 9.3 with sun_checks.xml
ruleset
[INFO] -----------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] -----------------------------------------------------------------
Quand Checkstyle bloque un build :
- Chaque non-conformité remonte avec ses détails:
Ligne trop longue, paramètres non final, imports globaux, etc
Un rapport détaillé est alors généré dans: /target/checkstyle.xml
<configuration>
//..
<failOnViolation>false</failOnViolation>
</configuration>
ou, en ligne de commande :
./mvnw checkstyle:check -Dcheckstyle.failOnViolation=false
Il affichera toujours les erreurs, mais le build ne sera plus “FAILURE”Permet de désactiver les règles trop strictes pour avoir un style plus souple
<configLocation>
config/checkstyle/google_checks.xml
</configLocation>
Recommandé pour les projets long terme
Utilisé uniquement en phase de migration ou de refactoring massif
→ Commentez les lignes du mode strict et utilisez le mode tolérant:# - name: Run Checkstyle
# run: ./mvnw checkstyle:check
- name: Run Checkstyle (non-blocking)
run: ./mvnw checkstyle:check
-Dcheckstyle.failOnViolation=false
Étant le développeur et le devOps, j'ai choisi le mode strict, ainsi je n'accumule pas de dette technique
En entreprise, en tant que devOps, j'aurais activé le mode tolérant, le temps que le développeur corrige toutes les erreurs relevés
Si Checkstyle n'est pas encore configuré, il utilisera la configuration par défaut
Cela permet de garder Checkstyle strict sans pénaliser le code généré
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<!-- Vérifie la longueur des lignes -->
<module name="LineLength">
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http|https"/>
</module>
<!-- Vérifie les tabulations -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<!-- Analyse syntaxique du code Java -->
<module name="TreeWalker">
<module name="UnusedImports"/>
<module name="AvoidStarImport"/>
<module name="Indentation"/>
<module name="NeedBraces"/>
<module name="MethodLength">
<property name="max" value="100"/>
</module>
<module name="ParameterName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
</module>
</module>
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<!-- Ignore Lombok-generated code -->
<suppress files=".*[/\\]model[/\\].*" checks="MissingJavadocMethod"/>
<suppress files=".*[/\\]entity[/\\].*" checks="MissingJavadocMethod"/>
<suppress files=".*[/\\]dto[/\\].*" checks="MissingJavadocMethod"/>
<!-- Ignore test files -->
<suppress files=".*Test\.java" checks="JavadocMethod"/>
</suppressions>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
<suppressionsLocation>checkstyle-suppressions.xml</suppressionsLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
Avantage: On garde Checkstyle strict sur le reste du code. Et, on évite les faux positifs sur le code Lombok ou boilerplate Spring Boot
$ ./mvnw -e SpotBugs:check
[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO] -----------------------< com.example:flashcards >----------------
[INFO] Building flashcards 0.0.1-SNAPSHOT
[INFO] from pom.xml
[INFO] -----------------------------[ jar ]------------------------------
[INFO] >>> spotbugs:4.8.6.2:check (default-cli) > :spotbugs @ flashcards >>>
[INFO] --- spotbugs:4.8.6.2:spotbugs (spotbugs) @ flashcards ---
[INFO] Fork Value is true
[INFO] Done SpotBugs Analysis....
[INFO] <<< spotbugs:4.8.6.2:check (default-cli) < :spotbugs @ flashcards <<<
[INFO]
[INFO] --- spotbugs:4.8.6.2:check (default-cli) @ flashcards ---
[INFO] BugInstance size is 0
[INFO] Error size is 0
[INFO] No errors/warnings found
[INFO] -----------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------------
pipeline CI sécurisé dès l'étape qualité
L'article suivant couvrira JaCoco, SonarCloud, et la Quality Gates, en local et dans un pipeline multi-branches