Jenkins PipelineJob DSL无法解释管道脚本中的变量

时间:2019-10-10 21:12:37

标签: jenkins groovy jenkins-pipeline pipeline dsl

我正在尝试使用jobDSL插入中的pipelineJob函数生成Jenkins管道,但是无法将参数从DSL传递到管道脚本。我有几个项目使用的本质上是相同的Jenkinsfile,只有几个步骤之间存在差异。我正在尝试使用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}..."
            }
        }
    }
}

我在AdditionalParameters中传递的变量在jobDSL脚本中解释;具有正确名称的管道会生成。问题在于变量没有传递到从工作空间读取的管道脚本中-生成的管道的Jenkins配置看起来与文件完全相同,而对变量没有任何解释。

我已经做了很多尝试来解释字符串,包括“ $ {environments}”,$ {environments},$ environments,\ $ environments的许多变体...我找不到任何工作。我也尝试过将文件读取为gstringImpl:

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

有人对我如何使变量传播到管道脚本有任何想法吗?我知道我可以只使用一个for循环对脚本文本执行string.replaceAll(),但这似乎很麻烦;一定有更好的方法。

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

我想出了一种方法来完成这项工作。这不是我想要的,而是在作业创建过程中隐式解释了文件的字符串内容,但是它确实有效。它只是增加了一个额外的步骤。

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}

答案 2 :(得分:0)

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

由于环境变量是字符串,所以它们有一定的局限性,但是它应该适用于基本内容

例如:

//job-dsl
pipelineJob('example') {
    environmentVariables {
        // these vars could be specified by parameters of this job
        env('repository', 'blah')
        env('environments', "a,b,c"]) //comma separated string
    }
    displayName('Pipeline')
        definition {
            cps { 
                script(readFileFromWorkspace(pipeline.groovy))
            }
        }
    }
}

然后在管道中:

//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
    }
}