【问题标题】:Jenkins Copy Artifact parse copied build idJenkins复制工件解析复制的构建ID
【发布时间】:2017-10-06 08:04:50
【问题描述】:

我在 Jenkins 2.73.1 中使用多分支管道 Copy Artifact Plugin 从其他两个管道获取最后成功的工件,请参阅我的 Jenkinsfile:

def branchname = "${BRANCH_NAME}".replace("/", "%2F")
pipeline {
  agent {
    label 'windows'
  }
  stages {
    stage('get artifacts') {
      steps {
        script {
          parallel('get-backend': {
            step([$class: 'CopyArtifact', projectName: "backend/${branchname}", target: 'input/backend'])
          },
          'get-frontend': {
            step([$class: 'CopyArtifact', projectName: "frontend/${branchname}", target: 'input/frontend'])
          })
        }
      }
    }
  }
}

在构建日志中我看到例如:

...
[Pipeline] script
[Pipeline] {
[Pipeline] parallel
[Pipeline] [get-backend] { (Branch: get-backend)
[Pipeline] [get-frontend] { (Branch: get-frontend)
[Pipeline] [get-backend] step
[Pipeline] [get-frontend] step
[get-frontend] Copied 344 artifacts from "frontend » foo/bar" build number 17
[Pipeline] [get-frontend] }
[get-backend] Copied 2'287 artifacts from "backend » foo/bar" build number 3
[Pipeline] [get-backend] }
[Pipeline] // parallel
[Pipeline] }
[Pipeline] // script
...

问题/目标:我想将前端和后端的内部版本号(在日志见“内部版本号 17”和“内部版本号 3”)。

Jenkins Pipeline - Reading previous stage log 的问题中,我读到可以将 sh 脚本的标准输出重定向到 groovy 变量中,如下所示:

def out = sh script: 'command', returnStdout: true

但是在我的管道中我需要使用 windows,在这种情况下,步骤也不是命令,而是一个“步骤”(包含类“CopyArtifact”,对于 Jenkins 来说还是新的,我只是让它工作谷歌搜索并发现一些使用这种语法的例子)。

我怎样才能实现我的目标?在这种情况下我应该解析整个日志还是有更优雅的解决方案?请在您的答案中提供一些代码,以便我直接测试。

【问题讨论】:

    标签: jenkins jenkins-plugins jenkins-pipeline


    【解决方案1】:

    您可以将内部版本号写入上游作业中的文件并将其包含在存档中。然后你复制那个工件。您可以使用管道实用程序步骤插件从文件中收集信息,但如果您保持文件简单(即只写内部版本号),那么类似这样的内容将为您提供内部版本号:

    def backendBuildId = sh script: "cat backendBuild.txt", returnStdout: true
    

    或在 Windows 上:

    def backendBuildId = bat script: "type backendBuild.txt", returnStdout: true
    

    【讨论】:

    • 考虑到问题(rest api 在我们的设置中不方便,因为我们需要身份验证才能访问 URL,而 Windows 的 gnu wget 似乎不能正确处理这个问题),这是最好的(并且最容易实现)为我们的案例提供答案。
    【解决方案2】:

    您无法获得 Jenkins 步骤的输出,只有 sh 步骤允许,但在这种情况下,您将获得输出或内部 sh(或 bat)命令。

    但是,在您的情况下,它非常简单,因为您只需要其他内部版本号,您可以使用 Jenkins API,如 this question 中所述:

    def backendBuildId = sh script: "wget http://yourjenkinsurl/job/backend/${branchname}/lastSuccessfulBuild", returnStdout: true
    def frontendBuildId = sh script: "wget http://yourjenkinsurl/job/frontend/${branchname}/lastSuccessfulBuild", returnStdout: true
    

    更多详情,请查看您的 Jenkins 中的API details

    【讨论】:

    • 根据作业的时间和并发性,这确实有可能出现竞争条件。如果前端或后端作业恰好在复制工件和运行 wget 之间完成,则结果可能不匹配。
    • 在我的例子中,我并行获得了这两个工件,而且我们并没有真正经常同时构建它们,所以在我们的例子中它可能会起作用。在 get 步骤之前运行这 2 个 sh 命令可能是个好主意。
    • 您的答案不起作用,正如我在我的问题中所说,我正在使用 Windows,并按照您上面指定的方式调用 wget 命令,使用 sh 给了我此错误:java.io.IOException: CreateProcess error=2, The system cannot find the file specified [...] java.io.IOException: Cannot run program "nohup"。无论如何,我尝试使用 bat 而不是 sh,它失败了,因为 Forbidden 403:它需要身份验证。没有更聪明的方式来使用 jenkins api,因为它运行自己的管道,再次进行身份验证没有多大意义。它应该使用内部命令...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多