是否可以从管道步骤动态设置Jenkins作业参数?

quhf5bfb  于 2022-12-03  发布在  Jenkins
关注(0)|答案(4)|浏览(165)

我有以下(简化)Jenkins管道代码。
jobParams.groovy

List get(Object paramVars = {}) {

    def params = []

    params += [
        choice(
            choices: ['branch', 'tag'],            
            name: 'RELEASE_TYPE'
        ),
        string(
            defaultValue: '',
            name: 'VERSION'
        ),
    ]

    return params
}

pipeline.groovy

def call() {

    properties([
        parameters(
            jobParams.get()
        )
    ])

    pipeline {
        agent { label 'deploy-slave' }

        stages {
            stage('Prepare') {
                steps {
                    script {
                        // Do some logic here and set a job parameter?
                    }
                }
            }
        }
    }
}

这很好用。当管道启动时,作业参数被设置,并可用于下一次作业运行。
但是,是否也可以在管道步骤中的某些逻辑之后动态设置作业参数?

ef1yzkbh

ef1yzkbh1#

原来这是相当容易的!
我在我的共享管道库中创建了一个jobProperties.groovy文件,它组成参数列表并调用properties()函数。

def call() {
    params = [
        string(
            defaultValue: '',
            description: 'Version to deploy',
            name: 'VERSION'
        ),
    ]

    if (env.HANDLER == 'ansible') {
        params += [
            string(
                defaultValue: '',
                description: 'DEPLOY_ARGS | Ad hoc "ansible-playbook" args. Example to limit hosts to' +
                    ' deploy to "-l somehost"',
                name: 'DEPLOY_ARGS'
            ),
        ]
    } else if (env.HANDLER == 'capistrano') {
        params += [
            string(
                defaultValue: '',
                description: 'DEPLOY_ARGS | Ad hoc "cap" args. Example to limit hosts to' +
                    ' deploy to "-z somehost"',
                name: 'DEPLOY_ARGS'
            ),
        ]
    }

    properties([
        parameters(
            params
        )
    ])
}

pipeline.groovy

def call() {
    pipeline {
        agent { label 'deploy-slave' }

        stages {
            stage('Prepare') {
                steps {
                    script {
                        jobProperties()
                    }
                }
            }
        }
    }
}

我认为,如果没有共享管道库,jobParams.groovy的代码也可以直接放在管道的script {} Package 器中。

ehxuflar

ehxuflar2#

是的,但是有一些复杂性,因为params是一个不可变的Map。
当我们想要在作业执行期间更改参数时,我们使用我们编写的共享库函数。
这可能需要管理员批准脚本。
第一个函数用于设置一个新的字符串参数,或者用一个新值更新一个已有的字符串参数。第二个和第三个作业只是为当前作业或其他作业的选择参数添加一个新选项的接口。第四个是这个选择添加逻辑的主要部分。(不直接调用)
organizationFolder基于我们使用的Github分支源插件。

/**
     * Change param value during build
     *
     * @param paramName new or existing param name
     * @param paramValue param value
     * @return nothing
     */
    def setParam(String paramName, String paramValue) {
        List<ParameterValue> newParams = new ArrayList<>();
        newParams.add(new StringParameterValue(paramName, paramValue))
        try {
            $build().addOrReplaceAction($build().getAction(ParametersAction.class).createUpdated(newParams))
        } catch (err) {
            $build().addOrReplaceAction(new ParametersAction(newParams))
        }
    }

    /**
     * Add a new option to choice parameter for the current job
     *
     * @param paramName parameter name
     * @param optionValue option value
     * @return nothing
     */
    def addChoice(String paramName, String optionValue) {
        addChoice($build().getParent(), paramName, optionValue)
    }

    /**
     * Add a new option to choice parameter to the given job
     *
     * @param paramName parameter name
     * @param optionValue option value
     * @return nothing
     */
    def addChoice(String jobName, String paramName, String optionValue) {
        List jobNames = jobName.tokenize("/")
        Job job = ((OrganizationFolder)Jenkins.getInstance().getItem(jobNames[0])).getItem(jobNames[1]).getItem(jobNames[2])

        addChoice(job, paramName, optionValue)
    }

    /**
     * Add a new option to choice parameter to the given job
     * Will be added as the first (default) choice
     * @param job job object
     * @param paramName parameter name
     * @param optionValue option value
     * @return
     */
    def addChoice(Job job, String paramName, String optionValue) {
        ParametersDefinitionProperty paramsJobProperty = job.getProperty(ParametersDefinitionProperty.class);
        ChoiceParameterDefinition oldChoiceParam = (ChoiceParameterDefinition)paramsJobProperty.getParameterDefinition(paramName);
        List<ParameterDefinition> oldJobParams = paramsJobProperty.getParameterDefinitions();
        List<ParameterDefinition> newJobParams = new ArrayList<>();

        for (ParameterDefinition p: oldJobParams) {
            if (!p.getName().equals(paramName)) {
                newJobParams.add(0,p);
            }
        }

        List<String> choices = new ArrayList(oldChoiceParam.getChoices());

        choices.add(0,optionValue);

        ChoiceParameterDefinition newChoiceParam = new ChoiceParameterDefinition(paramName, choices, oldChoiceParam.getDefaultParameterValue().getValue(), oldChoiceParam.getDescription());
        newJobParams.add(newChoiceParam);

        ParametersDefinitionProperty newParamsJobProperty = new ParametersDefinitionProperty(newJobParams);
        job.removeProperty(paramsJobProperty);
        job.addProperty(newParamsJobProperty);
    }
ovfsdjhp

ovfsdjhp3#

如上所述,paramsMap是不可变的,但是,正如所述here Jenkins还为每个构建参数创建了一个环境变量
因此,我用来覆盖构建参数的选项是使用环境变量,而不是参数Map中的值,例如:

if (environment == "PRD") {
    env.vpc_id = 'vpc-0fc6d952bbbf0000'
}
// Now run your script or command that refers to the environment var
sh './script.sh'
dtcbnfnu

dtcbnfnu4#

我猜你是在谈论动态地决定一个作业的下游参数。它肯定可以通过下面的代码描述的方式来完成。

@Library("shared-library") _
Map buildDetails = [:]
downStreamParams = [["\$class: 'StringParameterValue', name: 'TARGET_WORKSPACE', value: 'prod'"]]
pipeline {
    agent {
        label 'builds'
    }
    stages {
        stage('Get Details'){
            steps {
                script {
                    buildDetails = [
                      "releaseType":"minor",
                      "workspace":"prod",
                      "featureType":"ENHANCEMENT",
                      "PARAMS=Jenkins_Controller_Image":true,
                      "PARAMS=APPLY":true,
                      "PARAMS=PLUGIN_CLEANUP":true,
                      "PARAMS=RESTART":true,
                    ]
                    buildDetails.each{ key, value ->
                        println("$key:$value")
                        if(key.contains("PARAMS=")){
                            "[\$class: 'BooleanParameterValue', name: \"${key.split('=')[1]}\", value: true]"
                        }
                    }
                }
            }
        }
        stage("Build"){
            steps{
                script{
                    job = "build( job: jobFullName,parameters: ${downStreamParams},propagate: true,wait: true)"
                    evaluate(job)
                }
            }
        }
    }
}

相关问题