是否可以通过管道步骤设置Jenkins作业参数?

时间:2019-06-12 09:16:11

标签: jenkins jenkins-pipeline

我有以下(简化的)詹金斯管道代码。

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

这很好。当管道启动时,作业参数将被设置并在下次运行时可用。

但是,在流水线步骤中经过一些逻辑之后,是否还可以设置作业参数?

3 个答案:

答案 0 :(得分:1)

事实证明很简单!

我在共享管道库中创建了一个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的代码也可以直接放在管道的脚本{}包装器中。

答案 1 :(得分:0)

是的,但由于params是一成不变的地图,因此会带来一些麻烦。

我们要在作业执行过程中更改参数时使用编写的共享库函数。

这可能需要管理员才能批准脚本。

第一个功能是用于设置新的字符串参数,或使用新值更新现有字符串参数。 第二和第三作业只是用于为当前作业或其他作业的选择参数添加新选项的界面。 第四点是这种选择增加逻辑的主要苦恼。 (不直接调用)

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);
    }

答案 2 :(得分:0)

如前所述,params 映射是不可变的,但是,如所述here Jenkins 还为每个构建参数创建了一个环境变量

所以我用来覆盖构建参数的选项是使用环境变量而不是参数映射中的值,例如:

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