launch a sonar analysis for the code of a pullRequest with Jenkinsfile and maven

Viewed 1830

Currently on my project, each pull-Request on the organization-repository are build automatically by Jenkins, as specified in a jenkinsfile. When the build end, a message in send by Jenkins to github with the status of the build of this project.

I want to send a Sonar analyse to the conversation of the pull-request, but only for the file/code who have been updated by the pull request.

info for the bounty:

  • It need to use a jenkinsFile (adding a full jenkinsfile in your response will be appreciate)
  • the result should appear in the pullRequest page of github only for the code updated by the pullRequest.
3 Answers

As you haven't received an answer in 10 months i am going to help where i can Here is my working example for GitLab but you should be able to change this as the plugins are similar (https://wiki.jenkins.io/display/JENKINS/GitHub+Plugin#GitHubPlugin-Settingcommitstatus):

#!groovy

pipeline {
    options {
        buildDiscarder(
            logRotator(artifactDaysToKeepStr: '21', artifactNumToKeepStr: '4', daysToKeepStr: '21', numToKeepStr: '4')
        )
        gitLabConnection('GitLab')
    }

    agent any
    tools {
        maven 'Default Maven'
        jdk 'DefaultJDK'
    }

    stages {
        stage('Build') {
            steps {
                sh "mvn clean install -U"
            }
        }

        stage('Source Code Analysis') {
            steps {
                withMaven() {
                    sh "mvn " +
                        "-Dsonar.branch='${env.BRANCH_NAME}' " +
                        "-Dsonar.analysis.mode=preview " +
                        "-Dsonar.gitlab.commit_sha=\$(git log --pretty=format:%H origin/master..'${env.BRANCH_NAME}' | tr '\\n' ',') " +
                        "-Dsonar.gitlab.ref_name='${env.BRANCH_NAME}' " +
                        "sonar:sonar"
                }
                withMaven() {
                    sh "mvn -Dsonar.branch='${env.BRANCH_NAME}' sonar:sonar"
                }
            }
        }
    }

    post {
        success {
            echo 'posting success to GitLab'
            updateGitlabCommitStatus(name: 'jenkins-build', state: 'success')
        }
        failure {
            echo 'posting failure to GitLab'
            updateGitlabCommitStatus(name: 'jenkins-build', state: 'failed')
        }
        always {
            deleteDir()
        }
    }
}

This includes various bits but covers what you are trying to do, the sonar analysis occurs in two parts preview (which comments on the commit and these comments are transferred to a merge request when opened) and then a normal analysis afterwords

Within the project pom i also have defined:

<sonar.gitlab.project_id>${gitlab.project_id}</sonar.gitlab.project_id>
<sonar.gitlab.unique_issue_per_inline>true</sonar.gitlab.unique_issue_per_inline>
<sonar.gitlab.user_token>GITLAB_USER_TOKEN</sonar.gitlab.user_token>
<sonar.gitlab.url>${git.hostname.url}</sonar.gitlab.url>

If you add these and replace the missing bits i believe this will solve your issue.

Edit: I believe you need the following options for github instead of the GitLab one:

-Dsonar.analysis.mode=preview \
-Dsonar.github.pullRequest=$PULL_REQUEST_ID \
-Dsonar.github.repository=myOrganisation/myProject \
-Dsonar.github.oauth=$GITHUB_ACCESS_TOKEN \
-Dsonar.host.url=https://server/sonarqube \
-Dsonar.login=$SONARQUBE_ACCESS_TOKEN

I had several GitHub projects that needed to add Sonar scans. So, I took a slightly more generic approach to the execution of the scan by getting the org and repo from the URL. This allows for both main branch and pull request branch scans. NOTE: This requires that the Jenkins server have the plugin installed for GitHub Branch Source to expose the CHANGE_* environment variables.

void runSonarScanner() {
    def changeUrl = env.GIT_URL.split("/")
    def org = changeUrl[3]
    def repo = changeUrl[4].substring(0, changeUrl[4].length() - 4)
    if (env.CHANGE_ID != null) {
        sh "mvn -B sonar:sonar \
            -Dsonar.projectKey=${org}_${repo} \
            -Dsonar.pullrequest.provider=GitHub \
            -Dsonar.pullrequest.github.repository=${org}/${repo} \
            -Dsonar.pullrequest.key=${env.CHANGE_ID} \
            -Dsonar.pullrequest.branch=${env.CHANGE_BRANCH} \
            -Dsonar.pullrequest.base=${env.CHANGE_TARGET}"
    } else {
       sh "mvn -B sonar:sonar \
           -Dsonar.projectKey=${org}_${repo} \
           -Dsonar.branch.name=${env.BRANCH_NAME}"
    }
}

The above groovy definition can be used in the Jenkinsfile like:

stage ('Analyze') {
    when {
        anyOf {
            changeRequest()
            branch "main"
        }
    }
    tools {
        maven 'maven-3.6.0'
        jdk 'jdk11'
    }
    steps {
        withSonarQubeEnv('MySonar') {
            runSonarScanner()
        }
    }
}

This requires that the SonarQube Scanner Server plugin to be installed and configured with a "MySonar" ID in Jenkins->Configuration under Sonar servers.

Related