Jenkins dynamic declarative pipeline parameters

For anyone needing a declarative pipeline syntax option, I found a good solution in another question, which helped me.

This is my suggestion based on it. You should be able to generate a more dynamic list with the code that creates the ${WORKSPACE}/list file

pipeline {
    agent any
    stages {
        stage("Release scope") {
            steps {
                script {
                    // Prepare a list and write to file
                    sh "echo \"patch\nminor\nmajor\" > ${WORKSPACE}/list"

                    // Load the list into a variable
                    env.LIST = readFile (file: "${WORKSPACE}/list")

                    // Show the select input
                    env.RELEASE_SCOPE = input message: 'User input required', ok: 'Release!',
                            parameters: [choice(name: 'RELEASE_SCOPE', choices: env.LIST, description: 'What is the release scope?')]
                }
                echo "Release scope selected: ${env.RELEASE_SCOPE}"
            }
        }
    }
}

I hope this helps


There is another solution: you can use the "properties" step before "pipeline" - there you can use the active choice plugin too:

properties([
    parameters([
        [
            $class: 'ChoiceParameter', 
            choiceType: 'PT_SINGLE_SELECT', 
            description: '', 
            filterable: false, 
            name: 'Release', 
            randomName: 'choice-parameter-21337077649621572', 
            script: [
                $class: 'GroovyScript', 
                fallbackScript: '', 
                script: '''// Find relevant AMIs based on their name
                    def sout = new StringBuffer(), serr = new StringBuffer()
                    def proc = '/usr/bin/aws --region eu-west-1 ec2 describe-images \
                            ' --owners OWNER --filter Name=name,Values=PATTERN \
                            ' --query Images[*].{AMI:Name} --output  text'.execute()
                    proc.consumeProcessOutput(sout, serr)
                    proc.waitForOrKill(10000)
                    return sout.tokenize()'''
            ]
        ]
    ])
])
pipeline {
    ...
}

The only thing is that first time you start your build, it would fail. Second time you start it it should be a "build with parameter".

Hope it helps.


what about user input:

def findAMIs() {
    return UUID.randomUUID().toString().split('-').join('\n')
}

node{
    def userInput = input(
        id: 'userInput', message: 'input parameters', parameters: [
            [
                $class: 'ChoiceParameterDefinition',
                name: 'ami',
                choices: findAMIs(),
                description: 'AMI',
            ],
        ]
    )

    echo ("Selected AMI :: "+userInput)
}

after i been into the same boat and reading the instructions from https://www.jenkins.io/doc/book/pipeline/jenkinsfile/ 'Handling parameters' section i came with a very easy way since we can run properties before everything else.

put this quick example and modify to your liking, i am creating 2 multiple choose options, one will be hard codded and the other one will use the function at the bottom (outside pipeline node) under the choose options you can use the script{} step.

properties([
            [
            $class: 'RebuildSettings', autoRebuild: false, rebuildDisabled: false],
            parameters
            (
                [
                    choice(choices: ['opt1', 'opt2', 'opt3'], description: 'desc', name: 'bla'),
                    choice(choices: script{return_list()}, description: 'some letter', name: 'ble')
                ]
        )
    ]
 )

pipeline {
    agent{
        label "Linux"
    }

    stages{
        stage("frist"){
            steps{
                echo "${params.bla}"
                echo "${params.ble}"
            }
        }
    }
}

def return_list(){
    if ("${JOB_NAME}".contains("bla")){
        env.list_users = "1\n 2\n 3\n"
    }else{
        env.list_users = "a\n b\n c\n"
    }
    return env.list_users
}

you can also put them into a step

stages{
    stage("add more params"){
        steps{
                properties([
                    parameters([
                    choice(choices: [script{return_list()}
                    ],
                    description: 'This is the branch that we will build',
                    name: 'param3')
                    ])
                ])
            
        }
    }

be aware than you have to run it once so the next job will pick up the parameters.(only the latest properties node will appear in the UI)

with this method you can even go to decide if you want to display certain parameter in the UI or not. such

properties([
            [
            $class: 'RebuildSettings', autoRebuild: false, rebuildDisabled: false],
            parameters
            (
                script{
                    list_arguments()
                }   
        )
    ]
 )
pipeline {
    agent{
        label "Linux"
    }

    stages{
        stage("frist"){
            steps{
                echo "${params.bla}"
                echo "${params.ble}"
            }
        }
    }
}

def return_list(){
    if ("${JOB_NAME}".contains("bla")){
        env.list_users = "1\n 2\n 3\n"
    }else{
        env.list_users = "a\n b\n c\n"
    }
    return env.list_users
}

def list_arguments(){
    lista = return_list()
    if ("${JOB_NAME}".contains("word")){
        ch = [
            choice(choices: ['opt1', 'opt2', 'opt3'], description: 'desc', name: 'bla'),
            choice(choices: ["${lista}"], description: 'some letter', name: 'ble')
        ]

    }else{
        ch = [
            choice(choices: ['opt1', 'opt2', 'opt3'], description: 'desc', name: 'bla')
        ]
    } 
    return ch

}