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

Posted

技术标签:

【中文标题】詹金斯:无法在管道阶段定义变量【英文标题】:Jenkins: Cannot define variable in pipeline stage 【发布时间】:2017-02-11 11:20:04 【问题描述】:

我正在尝试创建一个声明性 Jenkins 管道脚本,但在简单的变量声明方面遇到了问题。

这是我的脚本:

pipeline 
   agent none
   stages 
       stage("first") 
           def foo = "foo" // fails with "WorkflowScript: 5: Expected a step @ line 5, column 13."
           sh "echo $foo"
       
   

但是,我收到此错误:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 5: Expected a step @ line 5, column 13.
           def foo = "foo"
           ^

我正在使用 Jenkins 2.7.4 和 Pipeline 2.4。

【问题讨论】:

【参考方案1】:

试试这个声明式管道,它的工作原理

pipeline 
   agent any
    stages 
      stage("first") 
        steps
          script 
           def foo = "foo" 
           sh "echo $foo"
              
            
          
        
       

【讨论】:

【参考方案2】:

你可以定义变量 global ,但是使用这个变量时必须写在脚本块中。

def foo="foo"
pipeline 
agent none
stages 
   stage("first") 
      script
          sh "echo $foo"
      
    
  

【讨论】:

如何在一个阶段中操作变量?例如。如果我想在stage("first") 中分配"bar" 的值怎么办?【参考方案3】:

我认为错误不是来自指定的行,而是来自前 3 行。试试这个:

node 
   stage("first") 
     def foo = "foo"
     sh "echo $foo"
   

我认为您有一些无效的额外行...

从 declaractive pipeline model documentation 看来,您似乎必须使用 environment 声明块来声明您的变量,例如:

pipeline 
   environment 
     FOO = "foo"
   

   agent none
   stages 
       stage("first") 
           sh "echo $FOO"
       
   

【讨论】:

您还可以将环境块添加到阶段(例如,如果您的变量依赖于之前步骤中所做的某些事情)。【参考方案4】:

同意@Pom12、@abayer。要完成答案,您需要添加脚本块

试试这样的:

pipeline 
    agent any
    environment 
        ENV_NAME = "$env.BRANCH_NAME"
    

    // ----------------

    stages 
        stage('Build Container') 
            steps 
                echo 'Building Container..'

                script 
                    if (ENVIRONMENT_NAME == 'development') 
                        ENV_NAME = 'Development'
                     else if (ENVIRONMENT_NAME == 'release') 
                        ENV_NAME = 'Production'
                    
                
                echo 'Building Branch: ' + env.BRANCH_NAME
                echo 'Build Number: ' + env.BUILD_NUMBER
                echo 'Building Environment: ' + ENV_NAME

                echo "Running your service with environemnt $ENV_NAME now"
            
        
    

【讨论】:

请注意,此示例假定 jenkins 可以访问已定义的环境变量“ENVIRONMENT_NAME”。 脚本块可以改变环境值吗? 是的,您可以更改脚本块内的环境值。【参考方案5】:

您正在使用 Declarative Pipeline,它需要 脚本步骤 来执行 Groovy 代码。与不需要这样做的Scripted Pipeline 相比,这是一个巨大的差异。

official documentation 表示以下内容:

脚本步骤采用脚本管道块并执行 在声明式管道中。

pipeline 
   agent none
   stages 
       stage("first") 
           script 
               def foo = "foo" 
               sh "echo $foo"
           
       
   

【讨论】:

【参考方案6】:

在 Jenkins 2.138.3 中有两种不同类型的管道。

声明式和脚本式管道。

“声明式管道是管道DSL的新扩展(它基本上是一个只有一个步骤的管道脚本,一个带有参数的管道步骤(称为指令),这些指令应该遵循特定的语法。这种新格式的要点是它更严格,因此对于管道新手来说应该更容易,允许图形编辑等等。 脚本化管道是高级需求的后备方案。”

jenkins pipeline: agent vs node?

这是在声明式管道中使用环境变量和全局变量的示例。据我所知,环境在设置后是静态的。

def  browser = 'Unknown'

pipeline 
    agent any
    environment 
    //Use Pipeline Utility Steps plugin to read information from pom.xml into env variables
    IMAGE = readMavenPom().getArtifactId()
    VERSION = readMavenPom().getVersion()


    
    stages 
        stage('Example') 
            steps 
                script 
                    browser = sh(returnStdout: true, script: 'echo Chrome')
                
            
        
        stage('SNAPSHOT') 
                when 
                    expression  
                        return !env.JOB_NAME.equals("PROD") && !env.VERSION.contains("RELEASE")
                    
                
                steps 
                    echo "SNAPSHOT"
                    echo "$browser"
                
            
            stage('RELEASE') 
                when 
                    expression  
                        return !env.JOB_NAME.equals("TEST") && !env.VERSION.contains("RELEASE")
                    
                
                steps 
                    echo "RELEASE"
                    echo "$browser"
                
            
    //end of stages 
//end of pipeline

【讨论】:

我从上面的代码中得到以下错误: [Pipeline] Start of Pipeline [Pipeline] readMavenPom [Pipeline] End of Pipeline org.jenkinsci.plugins.workflow.steps.MissingContextVariableException: required context class hudson. FilePath is missing 也许你忘了用提供这个的步骤包围代码,例如:node 不,它按原样工作。这是一个声明性管道。代理 any 意味着它可以在任何节点上工作 @pitchblack408,你说得对,我的管道顶部有 [agent none]。不知道你的意思是:环境在设置后是静态的?它们可以在脚本中更改,例如脚本 IMAGE = "newVal 例如,看IMAGE。它不是可以或应该由管道更改的变量。我的理解是,在定义为环境的一部分后,它会被视为静态值。【参考方案7】:

Jenkins Pipelines 的声明性模型有一个受限制的语法子集,它允许在 stage 块 - see the syntax guide for more info 中使用。您可以通过将步骤包装在 script ... 块中来绕过该限制,但结果是,您将失去对 script 块中语法、参数等的验证。

【讨论】:

如果我想在脚本块之外使用该变量怎么办? 要在脚本块外使用变量检查这个***.com/questions/43879733/…

以上是关于詹金斯:无法在管道阶段定义变量的主要内容,如果未能解决你的问题,请参考以下文章

詹金斯管道中的条件步骤/阶段

在詹金斯管道中复制工件

詹金斯管道:代理与节点?

如何在詹金斯管道中访问 git commit 消息 INSIDE sh STEP?

Jenkins Pipeline - 我们可以在 jenkins 管道之外运行工作吗?

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