如何在声明性 Jenkins 管道的各个阶段之间传递变量?

Posted

技术标签:

【中文标题】如何在声明性 Jenkins 管道的各个阶段之间传递变量?【英文标题】:How do I pass variables between stages in a declarative Jenkins pipeline? 【发布时间】:2017-10-21 08:14:08 【问题描述】:

如何在声明式管道的各个阶段之间传递变量?

在脚本化管道中,我收集的过程是写入临时文件,然后将文件读入变量。

如何在声明式管道中执行此操作?

例如我想根据 shell 操作创建的变量触发不同作业的构建。

stage("stage 1") 
    steps 
        sh "do_something > var.txt"
        // I want to get var.txt into VAR
    

stage("stage 2") 
    steps 
        build job: "job2", parameters[string(name: "var", value: "$VAR)]
    

【问题讨论】:

对于写入和读取部分,顺便说一句,有 shash/unstash。 使用environment variables 怎么样?就像全局变量一样? 【参考方案1】:

如果你想使用文件(因为脚本是生成你需要的值的东西),你可以使用readFile,如下所示。如果没有,请使用 shscript 选项,如下所示:

// Define a groovy local variable, myVar.
// A global variable without the def, like myVar = 'initial_value',
// was required for me in older versions of jenkins. Your mileage
// may vary. Defining the variable here maybe adds a bit of clarity,
// showing that it is intended to be used across multiple stages.
def myVar = 'initial_value'

pipeline 
  agent  label 'docker' 
  stages 
    stage('one') 
      steps 
        echo "1.1. $myVar" // prints '1.1. initial_value'
        sh 'echo hotness > myfile.txt'
        script 
          // OPTION 1: set variable by reading from file.
          // FYI, trim removes leading and trailing whitespace from the string
          myVar = readFile('myfile.txt').trim()
        
        echo "1.2. $myVar" // prints '1.2. hotness'
      
    
    stage('two') 
      steps 
        echo "2.1 $myVar" // prints '2.1. hotness'
        sh "echo 2.2. sh $myVar, Sergio" // prints '2.2. sh hotness, Sergio'
      
    
    // this stage is skipped due to the when expression, so nothing is printed
    stage('three') 
      when 
        expression  myVar != 'hotness' 
      
      steps 
        echo "three: $myVar"
      
    
  

【讨论】:

你也可以只使用def myVar,然后使用echo $myVar,如果你想把你的配置放在文件的顶部;) 写入文件不是很邪恶,还会创建不需要的磁盘吗? 你是对的@Dirkos,但有一种更好的方法可以在不涉及文件读/写的情况下实现所请求的内容。看到这个答案***.com/a/43881731/1053510 我正在从另一个答案重新发布我的评论,但我建议在第二阶段使用withEnv 包装器,以便您可以在sh 的上下文中使用该变量。否则,它将打印一个空字符串。至少它适用于 Jenkins 2.124。 @ConradB 只要您在并行阶段之前设置变量,在这里使用该技术应该可以正常工作(在上面的示例中,阶段“三”是您需要完成工作的地方并行执行)。【参考方案2】:

简单地说:

  pipeline 
        parameters 
            string(name: 'custom_var', defaultValue: '')
        

        stage("make param global") 
             steps 
               tmp_param =  sh (script: 'most amazing shell command', returnStdout: true).trim()
               env.custom_var = tmp_param
              
        
        stage("test if param was saved") 
            steps 
              echo "$env.custom_var"
            
        
  

【讨论】:

根据@KatieS 所指向的文档,参数 bloc 中定义的参数被访问为$params.custom_var 而不是$env.custom_var。两者都有效,但它们是一个不同的变量,可以包含不同的值。但是您使用参数 bloc 的解决方案对我来说可以通过 $params.custom_var 访问它们 我错了。 parameters 用于使用提供的参数并且似乎是不可变的,尝试在管道中设置它们(除了在参数中为它们分配默认值)将使阶段失败而没有任何错误消息。所以 env.custom_var 是要走的路。在这种情况下,可以省略参数 块。 这是否适用于多个 Jenkins 文件。我想要做的是将 repo 上的最新提交从 build.JenksinsFile 传递到 deploy.JenkinsFile ? 无论如何要在参数中插入类似 $workspace 的东西? like string(name: 'custom_var', defaultValue: "$workspace/a") 不确定这将如何工作。我不认为你可以在不使用“脚本”步骤的情况下直接在“步骤”块内设置变量。【参考方案3】:

我遇到了类似的问题,因为我想要一个特定的管道来提供变量,而许多其他管道使用它来获取这些变量。

我创建了一个 my-set-env-variables 管道

script

    env.my_dev_version = "0.0.4-SNAPSHOT"
    env.my_qa_version  = "0.0.4-SNAPSHOT"
    env.my_pp_version  = "0.0.2"
    env.my_prd_version = "0.0.2"
    echo " My versions  [DEV:$env.my_dev_version] [QA:$env.my_qa_version] [PP:$env.my_pp_version] [PRD:$env.my_prd_version]"

我可以在另一个管道 my-set-env-variables-test 中重用这些变量

script 

    env.dev_version = "NOT DEFINED DEV"
    env.qa_version  = "NOT DEFINED QA"
    env.pp_version  = "NOT DEFINED PP"
    env.prd_version = "NOT DEFINED PRD"


stage('inject variables') 

    echo "PRE DEV version = $env.dev_version"
    script 
    
       def variables = build job: 'my-set-env-variables'
       def vars = variables.getBuildVariables()
      //println "found variables" + vars
      env.dev_version = vars.my_dev_version
      env.qa_version  = vars.my_qa_version
      env.pp_version  = vars.my_pp_version
      env.prd_version = vars.my_prd_version
    


stage('next job') 
    echo "NEXT JOB DEV version = $env.dev_version"
    echo "NEXT JOB QA version = $env.qa_version"
    echo "NEXT JOB PP version = $env.pp_version"
    echo "NEXT JOB PRD version = $env.prd_version"




【讨论】:

以上是关于如何在声明性 Jenkins 管道的各个阶段之间传递变量?的主要内容,如果未能解决你的问题,请参考以下文章

Jenkins 声明性管道 - 如果不满足某些条件而不是跳过一个阶段,如何中止整个构建?

如何使用变量名作为声明性Jenkins的参数运行ArtifactoryMavenBuild?

在 Jenkins 声明式管道中使用 waitForQualityGate

詹金斯:无法在管道阶段定义变量

Jenkins声明性管道:如何从输入步骤中读取选择?

如何在 Jenkins 声明式管道中创建方法?