Jenkins pipelineJob DSL不解释管道脚本中的变量

Jenkins pipelineJob DSL不解释管道脚本中的变量,jenkins,groovy,jenkins-pipeline,pipeline,dsl,Jenkins,Groovy,Jenkins Pipeline,Pipeline,Dsl,我试图使用jobDSL插件中的pipelineJob函数生成Jenkins管道,但无法将参数从DSL传递到管道脚本。我有几个项目使用基本相同的Jenkins文件,只是在几个步骤上有所不同。我正在尝试使用JobDSL插件动态生成这些管道,并对其中的值进行解释,以使参数与DSL相匹配 我尝试了管道脚本中以及DSL中可以使用的字符串解释的几乎所有组合,但无法让Jenkins/groovy解释管道脚本中的变量 我正在管道步骤中调用作业DSL: def projectName = "myProject"

我试图使用jobDSL插件中的pipelineJob函数生成Jenkins管道,但无法将参数从DSL传递到管道脚本。我有几个项目使用基本相同的Jenkins文件,只是在几个步骤上有所不同。我正在尝试使用JobDSL插件动态生成这些管道,并对其中的值进行解释,以使参数与DSL相匹配

我尝试了管道脚本中以及DSL中可以使用的字符串解释的几乎所有组合,但无法让Jenkins/groovy解释管道脚本中的变量

我正在管道步骤中调用作业DSL:

def projectName = "myProject"
def envs = ['DEV','QA','UAT']
def repositoryURL = 'myrepo.com'

jobDsl targets: ['jobs/*.groovy'].join('\n'), 
    additionalParameters: [
        project: projectName, 
        environments: envs, 
        repository: repositoryURL
    ],
    removedJobAction: 'DELETE',
    removedViewAction: 'DELETE'
DSL如下所示:

pipelineJob("${project} pipeline") {
    displayName('Pipeline')
        definition {
            cps { 
                script(readFileFromWorkspace(pipeline.groovy))
            }
        }
    }
pipeline.groovy:

pipeline {
    agent any

    environment {
        REPO = repository
    }

    parameters {
        choice name: "ENVIRONMENT", choices: environments
    }

    stages {
        stage('Deploy') {
            steps {
                echo "Deploying ${env.REPO} to ${params.ENVIRONMENT}..."
            }
        }
    }
}
我在附加参数中传递的变量在jobDSL脚本中解释;将生成具有正确名称的管道。问题是变量没有传递到从工作区读取的管道脚本-生成的管道的Jenkins配置看起来与文件完全相同,没有对变量进行任何解释

我已经多次尝试解释字符串,包括${environments}、${environments}、\$environments、\$environments的许多变体……我找不到任何有效的。我还尝试以gstringImpl的形式读取该文件:

script("${readFileFromWorkspace(pipeline.groovy)}")

有没有人对如何让变量传播到管道脚本有什么想法?我知道我可以使用for循环在脚本文本上执行string.replaceAll,但这似乎很麻烦;一定有更好的办法。

我想出了一个办法让这一切顺利进行。这不是我喜欢的,在创建工作时隐式解释文件的字符串内容,但它确实有效;它只是增加了一个额外的步骤

import groovy.text.SimpleTemplateEngine

def fileContents = readFileFromWorkspace "pipeline.groovy"

def engine = new SimpleTemplateEngine()
template = engine.createTemplate(fileContents).make(binding.getVariables()).toString()

pipelineJob("${project} pipeline") {
    displayName('Pipeline')
    definition {
        cps { 
            script(template)
        }
    }
}

这将从您的工作区读取一个文件,然后将其用作带有绑定变量的模板。实现此功能所需的其他更改是转义Jenkinsfile脚本中使用的任何变量,如\${VARIABLE},以便在运行时而不是在构建作业时展开这些变量。任何你想在创造就业机会时扩展的变量都应该被引用为${VARIABLE}。

我想出了一个方法来实现这一点。这不是我喜欢的,在创建工作时隐式解释文件的字符串内容,但它确实有效;它只是增加了一个额外的步骤

import groovy.text.SimpleTemplateEngine

def fileContents = readFileFromWorkspace "pipeline.groovy"

def engine = new SimpleTemplateEngine()
template = engine.createTemplate(fileContents).make(binding.getVariables()).toString()

pipelineJob("${project} pipeline") {
    displayName('Pipeline')
    definition {
        cps { 
            script(template)
        }
    }
}

这将从您的工作区读取一个文件,然后将其用作带有绑定变量的模板。实现此功能所需的其他更改是转义Jenkinsfile脚本中使用的任何变量,如\${VARIABLE},以便在运行时而不是在构建作业时展开这些变量。创建作业时要展开的任何变量都应被引用为${VARIABLE}。

您可以通过在pipelineJob中定义环境变量,然后在管道中使用这些变量来实现所要实现的目标

它们有点有限,因为环境变量是字符串,但它应该适用于基本内容

例:

然后在管道中:

//pipeline.groovy
pipeline {
    agent any

    environment {
        REPO = env.repository
    }

    parameters {
        choice name: "ENVIRONMENT", choices: env.environments.split(',') 
        //note the need to split the comma separated string above
    }
}

您可以通过在pipelineJob中定义环境变量,然后在管道中使用这些变量来实现所要做的事情

它们有点有限,因为环境变量是字符串,但它应该适用于基本内容

例:

然后在管道中:

//pipeline.groovy
pipeline {
    agent any

    environment {
        REPO = env.repository
    }

    parameters {
        choice name: "ENVIRONMENT", choices: env.environments.split(',') 
        //note the need to split the comma separated string above
    }
}

您需要将完整的作业名称用作不带引号的变量。例如,如果JOBNAME是包含整个作业名称的参数:

pipelineJob(JOBNAME) {
    displayName('Pipeline')
        definition {
            cps { 
                script(readFileFromWorkspace(pipeline.groovy))
            }
        }
    }

您需要将完整的作业名称用作不带引号的变量。例如,如果JOBNAME是包含整个作业名称的参数:

pipelineJob(JOBNAME) {
    displayName('Pipeline')
        definition {
            cps { 
                script(readFileFromWorkspace(pipeline.groovy))
            }
        }
    }

我注意到的第一件事是,您试图访问params映射之外的参数值。尝试更改为params.ENVIRONMENT,看看它能让您走多远。此外,您在env映射之外隐式访问repo,这对您来说是不一致的。您在访问params映射之外的参数方面是正确的-进行更改确实会改善情况。然而,大问题仍然存在;我希望根据传递给作业DSL的值,将行选项名称:“环境”选项:环境解释为选项名称:“环境”选项:['DEV'、'QA'、'UAT']。我必须在DSL工作描述中创建参数,然后再在管道中创建参数。我认为cps{script}没有被解释,我认为Jenkins只是用脚本字符串作为步骤来创建作业,就这样。我注意到的第一件事是您试图访问params映射之外的参数值。尝试更改为params.ENVIRONMENT,看看它能让您走多远。此外,您正在环境映射之外隐式访问repo,这对您来说是不一致的
参数映射的改变确实改善了事情。然而,大问题仍然存在;我希望根据传递给作业DSL的值,将行选项名称:“环境”选项:环境解释为选项名称:“环境”选项:['DEV'、'QA'、'UAT']。我必须在DSL工作描述中创建参数,然后再在管道中创建参数。我认为cps{script}没有被解释,我认为Jenkins只是用脚本字符串作为步骤来创建作业,就这样。