Unable to show the single select when change the first one using active choice plugins

Hi,

I’m using the Active Choice plugin with two single select “Active Choices Parameter”. The first one shows the list of images (form Harbor) and the second one shows the versions of every image.

The problem is that, when I get an image from the first list, the second one doesn’t update.
I can show only the versions of the firt image of the first list. If I select another image from the first list and click on “build”, when I’ll came back to the form I can show the list of versions.

But I need to show them before to build, in order to choose the version to deploy.

This is my pipeline script, where I create two functions listImages() and def listVersionsFromImage(imageName).

Thank you in advance for any suggestions!

properties([
    parameters([
        // First choice parameter (Images)
        [$class: 'ChoiceParameter', 
            choiceType: 'PT_SINGLE_SELECT',
            description: 'Select a docker image',
            filterLength: 1,
            filterable: true,
            name: 'IMAGES',
            script: [$class: 'GroovyScript',
                fallbackScript: [
                    classpath: [], 
                    sandbox: true, 
                    script: 'return ["ERROR IMAGES"]'
                ],
                script: [
                    classpath: [], 
                    sandbox: true, 
                    script: listImages() 
                ]
            ]
        ],
        // Second choice parameter (Version)
        [$class: 'ChoiceParameter', 
            choiceType: 'PT_SINGLE_SELECT', 
            description: 'select version ',
            name: 'VERSION', 
            referencedParameters: 'IMAGES', 
            script: 
                [$class: 'GroovyScript', 
                fallbackScript: [
                    classpath: [], 
                    sandbox: true, 
                    script: 'return ["ERROR VERSION"]'
                ],                    
                script: [
                        classpath: [], 
                        sandbox: true, 
                        script: listVersionsFromImage(IMAGES)
                        ] 
                ]
            ]
    ])
])

pipeline {
   agent { label 'master' }  
   stages {

      stage('Printing selected choice') {

         steps {
              script {

            println IMAGES
            println VERSION


              }
         }
      }

   }
}

def listImages() {
    node("master") {
        configFileProvider([configFile(fileId: "global.conf", variable: 'globalConfigFile')]) {
            globalConf = readJSON returnPojo: true, file: globalConfigFile
        }

        def harborTokenId = globalConf.registry.token
        
        withCredentials([string(credentialsId: harborTokenId, variable: 'harborToken')]) {
        output = sh(returnStdout: true, script: "curl -X GET 'https://${globalConf.registry.url}/api/v2.0/projects/master/repositories?page=1&page_size=100' -H 'accept: application/json' -H 'authorization: Basic ${harborToken}' | jq '.[].name' | cut -d'/' -f2 | tr -d '\"' | sort ")
        def ouputAsArray = output.split('\n').findAll { it.trim() }
        def outputArrayWithQuotes = ouputAsArray.collect { "'${it}'" }

        return "${outputArrayWithQuotes}"
        }
    }    
}

def listVersionsFromImage(imageName) {
    node ('master') {
        configFileProvider([configFile(fileId: "global.conf", variable: 'globalConfigFile')]) {
            globalConf = readJSON returnPojo: true, file: globalConfigFile
        }

        def harborTokenId = globalConf.registry.token
        
        echo "imageName: ${imageName}"

        withCredentials([string(credentialsId: harborTokenId, variable: 'harborToken')]) {
        output = sh(returnStdout: true, script: "curl -X GET 'https://${globalConf.registry.url}/api/v2.0/projects/master/repositories/${imageName}/artifacts?page=1&page_size=10' -H 'accept: application/json' -H 'authorization: Basic ${harborToken}' | jq -r '.[].tags[].name' | sort -r ")
        
        echo "Versions: ${output}"
        
        def ouputAsArray = output.split('\n').findAll { it.trim() }
        
        echo "Versions one: $ouputAsArray"
        def outputArrayWithQuotes = ouputAsArray.collect { "'${it}'" }
        echo "Versions dos: $outputArrayWithQuotes"
        
        return "${outputArrayWithQuotes}"
        
        }
    }
}   

you can’t define the methods outside of the script attribute of the parameter and put them in the pipeline script itself.
Parameters are evaluated before the pipeline script is executed so the methods are not defined at that time.

1 Like

Thank you @mawinter69 for your suggestions, but I can’t solve the problems.
I’m newbie Jenkins and groovy.

I put the second function inside the groovy script parameter, but it doesn’t run.

Could you review my changes, please?
Currently the form show ERROR instead of the versions list.

properties([
    parameters([
        // First choice parameter (Images)
        [$class: 'ChoiceParameter', 
            choiceType: 'PT_SINGLE_SELECT',
            description: 'Select a docker image',
            filterLength: 1,
            filterable: true,
            name: 'IMAGES',
            script: [$class: 'GroovyScript',
                fallbackScript: [
                    classpath: [], 
                    sandbox: true, 
                    script: 'return ["ERROR IMAGES"]'
                ],
                script: [
                    classpath: [], 
                    sandbox: true, 
                    script: listImages() 
                ]
            ]
        ],
        // Second choice parameter (Version)
        [$class: 'ChoiceParameter', 
            choiceType: 'PT_SINGLE_SELECT', 
            description: 'select version ',
            name: 'VERSION', 
            referencedParameters: 'IMAGES', 
            script: [$class: 'GroovyScript', 
                fallbackScript: [
                    classpath: [], 
                    sandbox: true, 
                    script: 'return ["ERROR IMAGES"]'
                ],                  
                script: [
                    classpath: [], 
                    sandbox: true, 
                    script: '''
                    def listVersionsFromImage(imageName) {
                        node ('master') {
                            configFileProvider([configFile(fileId: "global.conf", variable: 'globalConfigFile')]) {
                                globalConf = readJSON returnPojo: true, file: globalConfigFile
                            }
                    
                            def harborTokenId = globalConf.registry.token
                            withCredentials([string(credentialsId: harborTokenId, variable: 'harborToken')]) {
                            output = sh(returnStdout: true, script: "curl -X GET 'https://${globalConf.registry.url}/api/v2.0/projects/master/repositories/${imageName}/artifacts?page=1&page_size=10' -H 'accept: application/json' -H 'authorization: Basic ${harborToken}' | jq -r '.[].tags[].name' | sort -r ")
                            
                            def ouputAsArray = output.split('\n').findAll { it.trim() }
                            def outputArrayWithQuotes = ouputAsArray.collect { "'${it}'" }
                            
                            return "${outputArrayWithQuotes}"
                            }
                        } 
                    
                        return  listVersionsFromImage(IMAGES)
                    '''    
                  ]
            ]
        ]    
    ])
])



pipeline {
   agent { label 'master' }  
   stages {

      stage('Printing selected choice') {

         steps {
              script {

            println IMAGES
            println VERSION


              }
         }
      }

   }
}


def listImages() {
    node("master") {
        configFileProvider([configFile(fileId: "global.conf", variable: 'globalConfigFile')]) {
            globalConf = readJSON returnPojo: true, file: globalConfigFile
        }

        def harborTokenId = globalConf.registry.token
        
        withCredentials([string(credentialsId: harborTokenId, variable: 'harborToken')]) {
        output = sh(returnStdout: true, script: "curl -X GET 'https://${globalConf.registry.url}/api/v2.0/projects/master/repositories?page=1&page_size=100' -H 'accept: application/json' -H 'authorization: Basic ${harborToken}' | jq '.[].name' | cut -d'/' -f2 | tr -d '\"' | sort ")
        def ouputAsArray = output.split('\n').findAll { it.trim() }
        def outputArrayWithQuotes = ouputAsArray.collect { "'${it}'" }
        echo "Images dos: $outputArrayWithQuotes"
        
        return "${outputArrayWithQuotes}"
        }
    }    
}
 
 

I think there is a sintax issue in my origional code, because the second block receive correctly the variable IMAGES.

I’ve just tested it using a fake code like this

                    script: '''
                        if (IMAGES.equals("aaa")){
                            return['1.1.1', '1.1.2']
                        }
                        else if (IMAGES.equals("bbb")) {
                            return['2.1.1', '2.2.2']
                        } 
                        else if (IMAGES.equals("ccc")){
                            return['3.1.1', '4.5.6']
                        }              

                        '''	

And choosing an image fro the first choice, so the form updates with the own version number.

Any advice how adapt that second part?

Thank you!

Your groovy script seem incorrect, it is plain jenkins groovy, not pipeline groovy. At least the node block should get removed.