简体   繁体   中英

Sonarqube quality gate stuck on pending when inside jenkins pipeline node

We're trying to add a Sonarqube scan as part of our Jenkins pipeline script. We have a multi-module maven project, and we're using the Maven Sonarqube plugin to run the aggregated scan. To initiate the scan we followed the instructions in Sonarqube's documentation as shown here (scroll down to the end of the page).

So the pipeline script looks something like this :

node {
    stage('SonarQube analysis') {
        withSonarQubeEnv('My SonarQube Server') {
            sh 'mvn clean package sonar:sonar'
        }
    }
}
stage("Quality Gate") {
    timeout(time: 1, unit: 'HOURS') { 
        def qg = waitForQualityGate() 
        if (qg.status != 'OK') {
            error "Pipeline aborted due to quality gate failure: ${qg.status}"
        }
    }
}

and it works as expected. But since we're using it in more than one file, we'd like to have as less duplicate code as possible, so we want to have it inside the node like this :

node {
    stage('SonarQube analysis') {
        withSonarQubeEnv('My SonarQube Server') {
            sh 'mvn clean package sonar:sonar'
        }
    }
    stage("Quality Gate") {
        timeout(time: 1, unit: 'HOURS') { 
            def qg = waitForQualityGate() 
            if (qg.status != 'OK') {
                error "Pipeline aborted due to quality gate failure: ${qg.status}"
            }
        }
    }
}

But for some reason, this gets the quality gate stuck on PENDING status until the timeout is reached. I'm trying to understand why this is happening, and what could be done to avoid moving the quality gate check outside the node.

Any help would be greatly appreciated!

waitForQualityGate performs an HTTP call to the SonarQube server.

Make sure your build node has HTTP access to your SonarQube instance (the Jenkins master having access to it does not imply build nodes also have it).

Regardless, as I said in a comment, using a waiting step inside a node is not a good idea in general.

I was also facing the same issue and I fixed it by adding sleep before waitForQualityGate stage

sleep 10
stage("Quality Gate") {
        timeout(time: 1, unit: 'HOURS') { 
            def qg = waitForQualityGate() 
            if (qg.status != 'OK') {
                error "Pipeline aborted due to quality gate failure: ${qg.status}"
            }
        }
    }

This could be a better way to retry.

def retryForTimeoutExceeded(count = 3, Closure closure) {
    for (int i = 1; i <= count; i++) {
        try {
            closure()
            break
        } catch (FlowInterruptedException error) {
            int retriesLeft = count - i
            def hasTimeoutExceeded = error.causes[0].getClass().toString() == 'class org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution$ExceededTimeout'
            println "Timeout Exceeded for clousre.\nRetries left: $retriesLeft"
            if (retriesLeft == 0 || !hasTimeoutExceeded) {
                throw error
            }
        }
    }
}

stage("Quality Gate") {
        retryForTimeoutExceeded {
            timeout(time: 5, unit: 'MINUTES') {
                // Just in case something goes wrong, pipeline will be killed after a timeout
                def qg = waitForQualityGate() // Reuse taskId previously collected by withSonarQubeEnv
                if (qg.status != 'OK') {
                    error "Pipeline aborted due to sonar quality gate failure: ${qg.status}"
                }
            }
        }
    }

Timeout can be configured accordingly

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM