如何在参数化构建中访问参数?

98

如何访问“Workflow” Jenkins 作业中“此构建是参数化的”部分设置的参数

测试用例

  1. 创建一个工作流作业。
  2. 启用“此构建是参数化的”选项。
  3. 添加一个字符串参数foo,默认值为bar text
  4. 将下面的代码添加到Workflow Script中:

    node()
    {
         print "DEBUG: parameter foo = ${env.foo}"
    }
    
  5. 运行任务。

结果

调试: 参数 foo = null


2
另一个误解(来自#jenkins中的autojack:[transcript](http://echelog.com/logs/browse/jenkins/1427925600))是您应该使用`$foo`,例如`if($PARAM =='true'){...}。那只是Groovy中的变量标识符。 $`仅在某些类型的字符串中作为元字符。 - Jesse Glick
要修改Jenkins参数,请尝试使用EnvInject插件。这里有一个示例:https://dev59.com/dGw05IYBdhLWcg3w11a0#7067223 - Noam Manos
10个回答

101

当使用工作流插件时,我认为变量直接可用,而不是通过env获得。尝试:

node()
{
    print "DEBUG: parameter foo = ${foo}"
}

2
正确的,如此处所述(https://github.com/jenkinsci/workflow-plugin/blob/master/TUTORIAL.md#build-parameters)。 - Jesse Glick
但是为了让它在shell任务中可用,我似乎必须分配给'env' - 这感觉很奇怪... 例如: env.PARAM = PARAM - domi
2
不,我错了 - 我使用的是 sh '''echo X''' 而不是 sh """echo X"""。 - domi
7
请使用双引号而不是单引号。后者会跳过插值操作。 - Henrique Gontijo
请确保您不要将“env”作为参数之一,因为它是一个保留关键字,无法正常工作。 - Yeikel
在大多数情况下,使用单引号是可以的,但有时候除非你使用双引号,否则会失败。有什么规则来确定使用单引号是否会失败? - HKK

84

我尝试了这个主题中的几个解决方案,它似乎可以工作,但我的值始终为true,我还遇到了以下问题:JENKINS-40235

我成功地在groovy的jenkinsfile中使用参数,使用以下语法:params.myVariable

下面是一个可行的示例:

解决方案

print 'DEBUG: parameter isFoo = ' + params.isFoo
print "DEBUG: parameter isFoo = ${params.isFoo}"

一个更详细(且可行)的示例:

node() {
   // adds job parameters within jenkinsfile
   properties([
     parameters([
       booleanParam(
         defaultValue: false,
         description: 'isFoo should be false',
         name: 'isFoo'
       ),
       booleanParam(
         defaultValue: true,
         description: 'isBar should be true',
         name: 'isBar'
       ),
     ])
   ])

   // test the false value
   print 'DEBUG: parameter isFoo = ' + params.isFoo
   print "DEBUG: parameter isFoo = ${params.isFoo}"
   sh "echo sh isFoo is ${params.isFoo}"
   if (params.isFoo) { print "THIS SHOULD NOT DISPLAY" }

   // test the true value
   print 'DEBUG: parameter isBar = ' + params.isBar
   print "DEBUG: parameter isBar = ${params.isBar}"
   sh "echo sh isBar is ${params.isBar}"
   if (params.isBar) { print "this should display" }
}

输出

[Pipeline] {
[Pipeline] properties
WARNING: The properties step will remove all JobPropertys currently configured in this job, either from the UI or from an earlier properties step.
This includes configuration for discarding old builds, parameters, concurrent builds and build triggers.
WARNING: Removing existing job property 'This project is parameterized'
WARNING: Removing existing job property 'Build triggers'
[Pipeline] echo
DEBUG: parameter isFoo = false
[Pipeline] echo
DEBUG: parameter isFoo = false
[Pipeline] sh
[wegotrade-test-job] Running shell script
+ echo sh isFoo is false
sh isFoo is false
[Pipeline] echo
DEBUG: parameter isBar = true
[Pipeline] echo
DEBUG: parameter isBar = true
[Pipeline] sh
[wegotrade-test-job] Running shell script
+ echo sh isBar is true
sh isBar is true
[Pipeline] echo
this should display
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

我发送了一个Pull Request来更新误导性的pipeline教程#build-parameters引用,该引用说道“它们可以作为相同名称的Groovy变量被访问”。;)

编辑:正如Jesse Glick所指出的那样: 发布说明提供了更多细节。

您还应该将Pipeline Job Plugin更新到2.7或更高版本,这样构建参数将被定义为环境变量,因此可以像全局Groovy变量一样访问。


4
参数仍然可以像以前一样使用,没有params(作为平面字符串,不支持默认值)。它们现在在技术上是环境变量,尽管您仍然可以使用简单表达式来引用它们的值,因为对于访问,env.前缀现在也是可选的。发行说明提供了更多详细信息。 - Jesse Glick
1
这真的帮助了我解决了我的问题:http://stackoverflow.com/questions/42115868/jenkins-groovy-url-get-parameter/42153457#42153457。非常感谢。 - Basti
有什么线索可以帮我解决这个问题吗:http://stackoverflow.com/questions/42277315/jenkins-groovy-extend-properties-array? - Basti
1
@Basti:Jon S的回答在你的问题/答案中是正确的,你必须只调用properties一次或每次重写所有参数。 - GabLeRoux
4
自版本0.8起,“属性”部分已更名为“选项”。使用选项代替。这不再适用。 - Carmageddon
显示剩余4条评论

17
当你添加一个构建参数foo时,它会被转换为类似于“裸变量”的东西,所以在你的脚本中应该这样做:

当您添加一个构建参数“foo”时,它将被转换为类似于“裸变量”的东西,因此在脚本中您需要这样操作:


node {
   echo foo
}

如果您查看工作流脚本的实现,您将看到在执行脚本时会动态生成一个名为WorkflowScript的类。所有脚本中的语句都在该类的上下文中执行。所有传递给此脚本的构建参数都会转换为属性,并可从该类中访问。

例如,您可以执行以下操作:

node {
    getProperty("foo")
}

如果你好奇,这里是我编写的一个工作流脚本,它试图打印出构建参数、环境变量和WorkflowScript类上的方法。

node {
   echo "I am a "+getClass().getName()

   echo "PARAMETERS"
   echo "=========="
   echo getBinding().getVariables().getClass().getName()
   def myvariables = getBinding().getVariables()
   for (v in myvariables) {
       echo "${v} " + myvariables.get(v)
   }
   echo STRING_PARAM1.getClass().getName()

   echo "METHODS"
   echo "======="
   def methods = getMetaClass().getMethods()

   for (method in methods) {
       echo method.getName()    
   } 

   echo "PROPERTIES"
   echo "=========="
   properties.each{ k, v -> 
       println "${k} ${v}" 
   }
   echo properties
   echo properties["class"].getName()

   echo "ENVIRONMENT VARIABLES"
   echo "======================"
   echo "env is " + env.getClass().getName()
   def envvars = env.getEnvironment()
   envvars.each{ k, v ->
        println "${k} ${v}"
   }
}

这里是我尝试的另一个代码示例,我想测试一下构建参数是否已设置。

node {
   groovy.lang.Binding myBinding = getBinding()
   boolean mybool = myBinding.hasVariable("STRING_PARAM1")
   echo mybool.toString()
   if (mybool) {
       echo STRING_PARAM1
       echo getProperty("STRING_PARAM1")
   } else {
       echo "STRING_PARAM1 is not defined"
   }

   mybool = myBinding.hasVariable("DID_NOT_DEFINE_THIS")
   if (mybool) {
       echo DID_NOT_DEFINE_THIS
       echo getProperty("DID_NOT_DEFINE_THIS")
   } else {
       echo "DID_NOT_DEFINE_THIS is not defined"
   }
}

2
对我来说,这会产生以下结果:org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: 脚本不允许使用方法java.lang.Class getName - Thomas Hirsch

10

请使用双引号而不是单引号。

例如,使用echo "$foo",而不是使用echo '$foo'

如果您配置了允许使用“带参数构建”选项的流水线,则这些参数可以作为相同名称的Groovy变量进行访问。请参见此处了解更多信息。

如果您不需要执行变量替换,可以省略分号(;),省略括号((和))并使用单引号(')而不是双引号(")。请参见此处。尽管我发现只有双引号(")是必需的才能使其起作用。


您的回答中的链接不再指向正确的内容。我知道这个答案有点过时了,但我刚好碰巧在寻找答案时发现了它。 - Siddharth Seth

9

在参数变量前添加前缀“params.”,例如:

params.myParam

不要忘记:如果您使用了myParam的某些方法,可能需要在“脚本批准”中进行批准。

7
您还可以尝试使用“参数”指令来使您的构建参数化并访问参数:
文档: Pipeline syntax: Parameters 示例:
pipeline{

agent { node { label 'test' } }
options { skipDefaultCheckout() }

parameters {
    string(name: 'suiteFile', defaultValue: '', description: 'Suite File')
}
stages{

    stage('Initialize'){

        steps{

          echo "${params.suiteFile}"

        }
    }
 }

4
希望以下代码对您有用:
def item = hudson.model.Hudson.instance.getItem('MyJob')

def value = item.lastBuild.getEnvironment(null).get('foo')

2
这太过繁琐,而且如果你正在使用“沙盒”模式或者项目有并发构建的话,甚至不能正常工作。 - Jesse Glick
你也可以使用 jenkins.model.Jenkins.instance - Noam Manos

2
以下代码片段为您提供了访问所有作业参数的方法。
    def myparams = currentBuild.rawBuild.getAction(ParametersAction)
    for( p in myparams ) {
        pMap[p.name.toString()] = p.value.toString()
    }

2
请注意,访问流水线脚本(流水线插件)内的构建参数的方式已更改。采用以下方法:
getBinding().hasVariable("MY_PARAM")

已经无法使用,请尝试以下替代方法:

def myBool = env.getEnvironment().containsKey("MY_BOOL") ? Boolean.parseBoolean("$env.MY_BOOL") : false

我尝试了这个,并且env.getEnvironment()返回以下错误: 脚本不允许使用方法org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction getEnvironment - GabLeRoux
1
@GabLeRoux 你可以在Jenkins中的“管理Jenkins”>“进程脚本批准”下添加权限(在某些情况下可能不是非常好的主意,因为这会降低安全性)。 - Maksim
2
确实,那可能有效,但我更喜欢保持安全风险低 :) 我设法让它工作并发布了这个答案 - GabLeRoux

1
根据Pipeline插件教程

如果您已经配置了管道以在构建时接受参数 - 使用参数构建 - 则它们可以作为相同名称的Groovy变量访问。

因此,请尝试直接访问变量,例如:

node()
{
     print "DEBUG: parameter foo = " + foo
     print "DEBUG: parameter bar = ${bar}"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接