【问题标题】:How To Capture and Format Json Response in Jenkins Pipeline如何在 Jenkins 流水线中捕获和格式化 Json 响应
【发布时间】:2021-07-20 16:14:37
【问题描述】:

我正在我的 Jenkinsfile 中运行 curl 命令。

    post {
      success {
        script {
            sh '''
            |SCORE=+1
            |GERRIT_COMMENT="$(cat <<-EOL
            |Sonar result was: SUCCESS
            |Report: ${Jenkins_URL}/job/${JOB_NAME}/${BUILD_NUMBER}/artifact/report1.txt
            |EOL
            |)"
            |curl -s -u ${apiToken}: ${Sonar_URL}/api/measures/component_tree?ps=100&s=qualifier,name&component=sonarqube&metricKeys=ncloc,bugs,vulnerabilities,code_smells,security_hotspots,coverage,duplicated_lines_density&strategy=children | json_pp -json_opt pretty,canonical > report1.txt
            |echo "Voting unsuccessful"
            '''.stripMargin().stripIndent()
            archiveArtifacts artifacts: 'report1.txt', fingerprint: true
            echo 'I Succeeded'
            }
    }

但我得到了错误 malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "(end of string)") at /usr/bin/json_pp

我无法使用 jq,因为它没有安装并且无法安装。

curl 命令在我的终端上运行良好,但在我的 Jenkins 管道中却失败了。

另外,当我这样做时,它会起作用。

    post {
      success {
        script {
            sh '''
            |SCORE=+1
            |GERRIT_COMMENT="$(cat <<-EOL
            |Sonar result was: SUCCESS
            |Report: ${Jenkins_URL}/job/${JOB_NAME}/${BUILD_NUMBER}/artifact/report1.txt
            |EOL
            |)"
            |echo "Voting unsuccessful"
            '''.stripMargin().stripIndent()
            sh """
            curl -s -u ${apiToken}: '${Sonar_URL}/api/measures/component_tree?ps=100&s=qualifier,name&component=sonarqube&metricKeys=ncloc,bugs,vulnerabilities,code_smells,security_hotspots,coverage,duplicated_lines_density&strategy=children' | json_pp -json_opt pretty,canonical > report1.txt
            """
            archiveArtifacts artifacts: 'report1.txt', fingerprint: true
            echo 'I Succeeded'
            }
    }

但它会在控制台输出中引发警告。

Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure. Affected argument(s) used the following variable(s): [apiToken]

请问我做错了什么?

在 Jenkins 管道中,如何使用 curl 将 JSON 响应正确传递到文件中?

【问题讨论】:

    标签: jenkins curl jenkins-pipeline jenkins-groovy jenkins-job-dsl


    【解决方案1】:

    我建议尽可能不要使用 shell 脚本。 Shell 脚本不是跨平台的,需要安装额外的工具(例如curl)。

    在您的情况下,curl 调用可以替换为httpRequest 步骤。

    首先让我们替换curl 调用并将结果保存在componentTree.json 文件中:

    httpRequest(
        url: "${Sonar_URL}/api/measures/component_tree?ps=100&s=qualifier,name&component=sonarqube&metricKeys=ncloc,bugs,vulnerabilities,code_smells,security_hotspots,coverage,duplicated_lines_density&strategy=children",
        authorization: 'id-of-credentials-which-was-used-to-create-the-apiToken-variable',
        outputFile: 'componentTree.json'
    )
    

    您希望将 JSON 数据格式化为人类可读的格式,因此我们使用 readJSONwriteJSON 步骤:

    def json = readJSON(file: 'componentTree.json')
    writeJSON(json: json, file: 'report1.txt', pretty: 4)
    

    现在report1.txt 文件包含使用缩进 4 格式化的 JSON。

    componentTree.json 文件只写入和读取一次,所以让我们减少 IO 操作的次数:

    def response = httpRequest(
        url: "${Sonar_URL}/api/measures/component_tree?ps=100&s=qualifier,name&component=sonarqube&metricKeys=ncloc,bugs,vulnerabilities,code_smells,security_hotspots,coverage,duplicated_lines_density&strategy=children",
        authorization: 'id-of-credentials-which-was-used-to-create-the-apiToken-variable'
    )
    def json = readJSON(text: response.content)
    writeJSON(json: json, file: 'report1.txt', pretty: 4)
    

    关于警告:

    警告:使用 Groovy 字符串插值将秘密传递给“sh”,这是不安全的。受影响的参数使用了以下变量:[apiToken]

    秘密永远不应该被插入,因为它们可能包含可以解释的特殊字符。示例:

    • 我的秘密:My' https://example.org; cat /etc/passwd; echo \
    • 命令:curl -u '${password}' https://private.server/path/file.txt

    插值后调用以下命令:

    curl -u 'My' https://example.org; cat /etc/passwd; echo \' https://private.server/path/file.txt
    

    有两种解决方法:

    • 如果apiToken 是环境变量:
      sh "curl -s -u \$apiToken: '${Sonar_URL}/api/measures/component..."
      
    • 如果 apiToken 是 Groovy 变量:
      withEnv(["CREDENTIALS=${apiToken}"]) {
          sh "curl -s -u \$CREDENTIALS: '${Sonar_URL}/api/measures/component..."
      }
      

    在这两种情况下,美元符号 ($) 在凭据之前被转义,这意味着 shell 脚本将解析它(它将从环境变量中获取)。

    【讨论】:

    • 非常感谢,阿加布里斯。我已经在我的私人 Jenkins 实例上尝试过这个解决方案,它很有魅力。不幸的是,我实际使用的 Jenkins 服务器没有安装 http_request 插件,所以看起来我不得不使用 curl。我只是不知道如何超越A secret was passed to "sh" using Groovy String interpolation, which is insecure. Affected argument(s) used the following variable(s): [apiToken] 错误。不过我学到了一些新东西。非常感谢!
    • 我添加了为什么不应使用字符串插值传递凭据的解释。
    猜你喜欢
    • 2016-11-10
    • 2019-11-09
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    相关资源
    最近更新 更多