解决 sonarQube Quality Gate 的全局 webhook

Work around global webhook for sonarQube Quality Gate

我有兴趣为我的项目添加质量门。在 Jenkins 构建后,我添加了一个脚本,用于在 SonarQube 服务器上创建一个项目并确定测试质量是否足够(可以找到代码来源 here)。脚本如下

stage('SonarCloud') {
      steps {
        withSonarQubeEnv('SonarQube') {

            sh 'mvn clean package sonar:sonar '

        }
      }
    }
stage("Quality Gate") {
      steps {
        timeout(time: 15, unit: 'MINUTES') { // If analysis takes longer than indicated time, then build will be aborted
            waitForQualityGate abortPipeline: true
            script{
                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}"
                }
            }
        }
      }
    }

问题是我的构建永远不会自行完成(它会在超时后中止。删除超时会使它看起来永远运行。话虽如此,分析已创建并放置在 SonarQube 服务器上)。这是我在超时前看到的消息:

SonarQube task 'AXUx0uqFm6myUuXQbknO' status is 'IN_PROGRESS'

Cancelling nested steps due to timeout

我的问题是我不是我们 SonarQube 服务器的管理员,所以我无法添加可以解决此问题的 webhook。我想知道是否有解决方法?

我试过更换

sh 'mvn clean package sonar:sonar '

sh 'mvn clean package sonar:sonar -Dsonar.webhooks.project=https://my-jenkins-server.com/sonarqube-webhook/'

但一无所获。

我也尝试适应,在类似的问题中讨论过,但也没有走多远。

实际上有一种方法可以解决这个问题。正确的解决方法是将 webhook 安装回 Jenkins,但您显然无法解决这个问题。

下一个“正确的”修复是使用 SonarQube REST api,但首先我需要解释“waitForQualityGate()”中发生的事情。

它做的第一件事是使用 REST api 端点“/api/ce/task”查看后台任务是否完成。它从“report-task.txt”文件中获取要检查的任务 ID,该文件的格式类似于属性文件。如果第一次检查不是 SUCCESS 或 ERROR,那么它会进入等待循环,等待调用 webhook。

因此,您可以通过简单地添加比后台任务花费的秒数更多的“睡眠”,然后调用“waitForQualityGate()”来实现一个非常便宜的修复。

更合适的修复方法如下:

def reportFilePath = "target/sonar/report-task.txt"
def reportTaskFileExists = fileExists "${reportFilePath}"
if (reportTaskFileExists) {
    echo "Found report task file"
    def taskProps = readProperties file: "${reportFilePath}"
    echo "taskId[${taskProps['ceTaskId']}]"
    while (true) {
        sleep 20
        def taskStatusResult    =
            sh(returnStdout: true,
               script: "curl -s -X GET -u ${authString} \'${sonarProps['sonar.host.url']}/api/ce/task?id=${taskProps['ceTaskId']}\'")
            echo "taskStatusResult[${taskStatusResult}]"
        def taskStatus  = new JsonSlurper().parseText(taskStatusResult).task.status
        echo "taskStatus[${taskStatus}]"
        // Status can be SUCCESS, ERROR, PENDING, or IN_PROGRESS. The last two indicate it's
        // not done yet.
        if (taskStatus != "IN_PROGRESS" && taskStatus != "PENDING") {
            break;
        }
    }
}