0

I have established Quality Gate for my Jenkins project via SonarQube. One of my projects have no tests at all, so in the analysis I see that the code coverage is 0%. By the quality gate rules (<60% coverage = fail) my pipeline should return an error. However, this does not happen. The quality gate says that the analysis was a success and quality gate is 'OK'. In another project, I removed some tests to make coverage be <60% and the quality gate passed once again, even though it was meant to fail.

I had an error related to the analysis always returning 0% coverage before, but managed to fix it (with help from this link). Found a lot of articles with the similar questions but with no answers on any of them. This post looks promising but I cannot find the suitable alternative to its suggestion.

It is worth mentioning that the analysis stage is done in parallel with another stage (to save some time). The Quality Gate stage comes shortly afterwards.

The relevant code I use to initialise the analysis for my project is (org.jacoco... bit is the solution to 0% coverage error I mentioned above):

sh "mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent verify sonar:sonar -Dsonar.host.url=${env.SONAR_HOST_URL} -Dsonar.login=${env.SONAR_AUTH_TOKEN} -Dsonar.projectKey=${projectName} -Dsonar.projectName=${projectName} -Dsonar.sources=. -Dsonar.java.binaries=**/* -Dsonar.language=java -Dsonar.exclusions=$PROJECT_DIR/src/test/java/** -f ./$PROJECT_DIR/pom.xml"

The full quality gate code (to clarify how my quality gate starts and finishes):

 stage("Quality Gate") {
      steps {
        timeout(time: 15, unit: 'MINUTES') { // If analysis takes longer than indicated time, then build will be aborted
            withSonarQubeEnv('ResearchTech SonarQube'){
                script{

                // Workaround code, since we cannot have a global webhook
                    def reportFilePath = "target/sonar/report-task.txt"
                    def reportTaskFileExists = fileExists "${reportFilePath}"

                    if (reportTaskFileExists) {
                        def taskProps = readProperties file: "${reportFilePath}"
                        
                        def authString = "${env.SONAR_AUTH_TOKEN}"                 
                        def taskStatusResult    =
                            sh(script: "curl -s -X GET -u ${authString} '${taskProps['ceTaskUrl']}'", returnStdout: true)
                            //echo "taskStatusResult[${taskStatusResult}]"
                        def taskStatus  = new groovy.json.JsonSlurper().parseText(taskStatusResult).task.status
                        echo "taskStatus[${taskStatus}]"

                        if (taskStatus == "SUCCESS") {
                            echo "Background tasks are completed"
                        } else {
                            while (true) {
                                sleep 10
                                taskStatusResult    =
                                    sh(script: "curl -s -X GET -u ${authString} '${taskProps['ceTaskUrl']}'", returnStdout: true)
                                    //echo "taskStatusResult[${taskStatusResult}]"
                                taskStatus  = new groovy.json.JsonSlurper().parseText(taskStatusResult).task.status
                                echo "taskStatus[${taskStatus}]"
                                if (taskStatus != "IN_PROGRESS" && taskStatus != "PENDING") {
                                    break;
                                }
                            }
                        }
                    } else {
                        error "Haven't found report-task.txt."
                    }

                    def qg = waitForQualityGate() // Waiting for analysis to be completed
                    if(qg.status != 'OK'){ // If quality gate was not met, then present error
                        error "Pipeline aborted due to quality gate failure: ${qg.status}"
                    }
                }
            }
        }
      }
    }
Joe
  • 337
  • 6
  • 21
  • Which branch you are performing analysis on ? If it’s feature branch or long lived branches (say master, release or develop) – Sourav Oct 27 '20 at 17:54
  • @SouravAtta On a branch I want analysis to happen (I am using multibranch project and it seems to work with the selected Git Branch) – Joe Oct 28 '20 at 09:57
  • Yeah, Is it a long lived branch or short lived branch ? May be you are doing analysis on short lived branch and the thus the qualitygate status is not correct. Because you cannot attach qulaitygate for short lived branch. It can be done only in hard-coded way. https://docs.sonarqube.org/7.9/branches/short-lived-branches/#:~:text=The%20short%2Dlived%20branch%20quality,)%20or%20Failed%20(red). – Sourav Oct 28 '20 at 12:24
  • @SouravAtta Based on an article you shared, I am not sure. I used my current Git branch for couple of weeks not, but because I was editing a lot, almost everyday, so that makes it short lived? (in eyes of quality gate that is) – Joe Oct 28 '20 at 12:38
  • @SouravAtta I have managed to hardcode my quality gate and now it works. Not ideal, but I can make do. My only problem is that my analysis at SonarQube UI, still says that QG has passed. How can I change it? I really would like to have my analysis on a server. Can I change status of my work to failed via API? – Joe Oct 28 '20 at 13:50
  • Yeah. You can fail the Jenkins job with api. – Sourav Oct 28 '20 at 14:40
  • @SouravAtta Sorry, what I meant to say is once my analysis is placed on a server, I can access it and see all the metrics. However, even when QG meant to fail, it stills says QG has passed. I can fail my pipeline via error functions but analysis's status is still remains the same on the server. How can I change SonarQube analysis's status to be marked as failed, so if anyone checks in the server, they can see that it failed? – Joe Oct 28 '20 at 14:50
  • could you paste in some screenshot of sonarqube UI where the result of QG is visible and also the branches are shown. – Sourav Oct 29 '20 at 03:06

1 Answers1

1

What is shown in the SonarQube UI for the project? Does it show that the quality gate failed, or not?

I don't quite understand what you're doing in that pipeline script. It sure looks like you're calling "waitForQualityGate()" twice, but only checking for error on the second call. I use scripted pipeline, so I know it would look slightly different.

Update:

Based on your additional comment, if the SonarQube UI says that it passed the quality gate, then that means there's nothing wrong with your pipeline code (at least with respect to the quality gate). The problem will be in the definition of your quality gate.

However, I would also point out one other error in how you're checking for the background task results.

The possible values of "taskStatus" are "SUCCESS", "ERROR", "PENDING", and "IN_PROGRESS". If you need to determine whether the task is still running, you have to check for either of the last two values. If you need to determine whether the task is complete, you need to check for either of the first two values. You're checking for completion, but you're only checking for "SUCCESS". That means if the task failed, which it would if the quality gate failed (which isn't happening here), you would continue to wait for it until you timed out.

David M. Karr
  • 14,317
  • 20
  • 94
  • 199
  • First of all, I forgot to remove first call for 'waitForQualityGate' call. My bad. I will update my code for you to see the full quality gate script. In simple words: once work around webhook is done, I check for quality gate – Joe Oct 28 '20 at 10:02
  • As for my UI, it says that QG passes everytime – Joe Oct 28 '20 at 13:03
  • Found my problem. You were right about defining QG incorrectly. Also, have the following warning in another of my projects ```WARN: Found multiple 'report-task.txt' in the workspace. Taking the first one.``` How can I delete all these report-task.txt files? And how can I ensure that I only have one at all times? – Joe Oct 29 '20 at 13:57
  • The project with the said warning is parametrised - the parameter determines which folder is to be used to for project building (each folder has some code, tests, POM files etc.). Tried to run ```rm``` command via shell function but didn't get anywhere. – Joe Oct 29 '20 at 14:09