Analyse SonarQube dans chaque PR Bitbucket

Objectif : faire une analyse SonarQube à chaque Pull Request, et afficher le résultat dans la PR de Bitbucket cloud

Jusqu’en version 7.6 de SonarQube, on pouvait utiliser le plugin https://github.com/mibexsoftware/sonar-bitbucket-plugin/.

Mais depuis SonarQube 7.7, il y a eu des changements qui font que ce plugin ne fonctionne plus. Il faut maintenant passer sur une version payante de SonarQube pour avoir des analyses multi-branches (au moins la version « Developer »), ou alors utiliser la version cloud SonarCloud.

Cependant, un plugin permet d’activer le multi-branches sur la version « community » (gratuite et open-source) de SonarQube : https://github.com/mc1arke/sonarqube-community-branch-plugin. Évidemment, il est « non officiel », dans le sens où il n’est pas officiellement supporté par l’éditeur, puisqu’il va à l’encontre de son modèle économique… Il y a quelques avertissements à lire sur la page github : à utiliser en connaissance de cause.

Installation et configuration

Il faut choisir la version du plugin correspondant à la version de SonarQube.

En l’occurrence, j’avais installé la version LTS de SonarQube : 7.9.x. Compte tenu du statut non-officiel du plugin en question, c’est probablement plus sûr : il est possible qu’il y ait un jeu du chat et de la souris entre l’éditeur et les mainteneurs du plugin. Utiliser une version LTS permet de bénéficier des correctifs de sécurité sans pour autant courir après la compatibilité de versions entre le plugin et SonarQube. Bref, c’est une version 1.3.x du plugin qu’il faut utiliser avec SonarQube 7.9.x (actuellement 1.3.2).

L’installation du plugin a une particularité : il faut le mettre à la fois dans les répertoires extensions/plugins/ et lib/common/. Quand on utilise SonarQube dans un conteneur Docker (c’était le cas), il faut donc ajouter un montage pour lib/common/sonarqube-community-branch-plugin-x.x.x.jar : c’est décrit dans le README. Et c’est un point à ne pas oublier lors des futures montées de version de SonarQube : il faudra mettre à jour ce plugin ainsi que son montage dans lib/common.

Ensuite, il faut le configurer. Pour Bitbucket cloud, le README n’est pas explicite, mais j’ai finalement trouvé l’information nécessaire sur https://github.com/mc1arke/sonarqube-community-branch-plugin/issues/227#issuecomment-673501579 :

  • Créer un « App Password » dans les « Personal Settings » du compte Bitbucket cloud
  • Encoder le login:app_password en base64, via la commande « echo -n USERNAME:APP_PASSWORD | base64 » (en mettant le login Bitbucket cloud en USERNAME et le APP_PASSWORD généré juste au-dessus)
  • Le résultat de cette commande doit être mis dans le champ token, et « https://api.bitbucket.org » dans l’URL. Tout ça dans Administration -> Configuration -> Pull Request (Zone « Integration with Bitbucket », en choisissant aussi BitBucketServer comme Provider)
  • Puis, pour chaque projet Sonar concerné, dans Administration -> General Settings -> Pull Request, renseigner le nom du groupe (ou user) Bitbucket dans ProjectKey, et le nom normalisé (slug) du repository dans Repository Slug

Lancement de l’analyse

En l’occurrence, l’analyse était lancée par Jenkins, mais ce serait la même chose via un autre outil.

Attention au fait que la ligne de commande est différente quand on fait l’analyse sur une branche « normale » ou sur une Pull Request (c’est indiqué dans le README, mais je me suis quand même fait avoir). Pour une branche :

mvn sonar:sonar -Dsonar.host.url=https://sonarurl -Dsonar.branch.name=${BRANCH_NAME} 

Et pour une PR :

mvn sonar:sonar -Dsonar.host.url=https://sonarurl -Dsonar.pullrequest.branch=${CHANGE_BRANCH} -Dsonar.pullrequest.base=${CHANGE_TARGET} -Dsonar.pullrequest.key=${CHANGE_ID}

Pour les PR, les noms des variables ${…} dépendent de la manière dont vous avez branché Bitbucket avec Jenkins. Dans cet exemple, il s’agit de ceux du bitbucket-branch-source-plugin : https://github.com/jenkinsci/bitbucket-branch-source-plugin/issues/229#issuecomment-612651306). Si vous utilisez https://github.com/jenkinsci/bitbucket-pullrequest-builder-plugin , il s’agit plutôt (dans l’ordre) de ${sourceBranch}, ${targetBranch} et ${pullRequestId}.

Si vous utilisez le bitbucket-branch-source-plugin, voici un exemple de Jenkinsfile :

pipeline {

    agent any
    options {
        ansiColor('xterm') // Optionnel, nécessite le plugin https://plugins.jenkins.io/ansicolor/ 
    }

    stages {
        stage ('Build') {steps {
            script {
                def lignedecommande = "mvn clean install"
                if(isUnix()) {
                    sh lignedecommande
                } else { 
                    bat lignedecommande
                }
            }
        }}
        stage('Analyse SonarQube') {steps {
                script {
                    def sonarparameters = "";
                    if (env.CHANGE_ID) {
                        // uniquement dans les Pull Requests
                        sonarparameters = " -Dsonar.pullrequest.branch=${CHANGE_BRANCH} -Dsonar.pullrequest.base=${CHANGE_TARGET} -Dsonar.pullrequest.key=${CHANGE_ID}";
                    }
                    else {
                        // pour les autres branches
                        sonarparameters = " -Dsonar.branch.name=${BRANCH_NAME}";
                    }
                    def lignedecommande = "mvn sonar:sonar -Dsonar.host.url=https://sonarurl" + sonarparameters;
                    if(isUnix()) {
                        sh lignedecommande
                    } else { 
                        bat lignedecommande
                    }
                }
        }}
    }
}

Patch de la version 1.3.2 du plugin

Dans la version 1.3.2, il y a un bug assez gênant : dans la PR Bitbucket, on a une URL HTTP à la place du message de Sonar à chaque ligne concernée. C’est un bug connu, et déjà corrigé : https://github.com/mc1arke/sonarqube-community-branch-plugin/pull/237 . Sauf qu’il a été corrigé dans une version ultérieure, et n’est pas inclus en version 1.3.2.

Donc je l’ai backporté, et ai généré une version patchée avec ce correctif : https://github.com/mossroy/sonarqube-community-branch-plugin/releases/tag/1.3.2-patch-mossroy

J’ai proposé que ce soit reporté upstream, et intégré dans une future version 1.3.3, en créant une PR : https://github.com/mc1arke/sonarqube-community-branch-plugin/pull/277. Le mainteneur semble OK pour ça. Si c’est bien le cas, je vous encourage à utiliser les versions 1.3.x officielles (>=1.3.3, dès qu’elles seront releasées) plutôt que ma version patchée.

Message d’erreur « target branch ‘…’ does not exist »

Lors des premiers essais, certains builds Maven d’analyse Sonar finissaient en erreur :

ERROR: Error during SonarQube Scanner execution
ERROR: Could not target requested branch
ERROR: Caused by: Target branch 'develop' does not exist

Cela se produit si la branche d’origine de la PR (en l’occurrence develop) n’est pas encore connue par Sonar.

Il était donc nécessaire de lancer un premier scan Sonar sur la branche develop pour que les scans des sous-branches fonctionnent.

Incident technique sur Bitbucket

Pour l’anecdote, j’ai eu du mal à faire marcher tout ça la première fois. Tout était configuré comme il faut, et pourtant rien ne s’affichait dans les PRs. En fait, j’ai pas eu de bol, et faisais mes tests en plein pendant des problèmes techniques chez Bitbucket : https://bitbucket.status.atlassian.com/incidents/4x6c856ctznk. Le lendemain, tout marchait!

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *