ActiveChoice Plugin question

Jenkins setup: Docker container with version 2.447

Currently, I am using the Active Choices plugin to configure my pipeline. I have 3 different parameters that are used to build the pipeline.

The 2nd parameter, updates on the value selected for the 1st parameter. The 3rd parameter, updates on the value selected for the 2nd parameter.

However, what I observe is that the value of the 3rd parameter remains the same for that particular build number ( irrespective of any different option selected in 2nd parameter). The 3rd parameter value(in the current build) is the value of the results from the click of 2nd parameter(in the previous build)

For eg: In the second parameter, I select branch2. IFF i had selected branch2 in my previous build for 2nd parameter, it would show me the values: model3,model4. IFF NOT, then some other values all together.

Image:
image

The MODEL_INFO is not updated there.

properties([     
	parameters([  
		[$class: 'CascadeChoiceParameter',             
		choiceType: 'PT_SINGLE_SELECT',             
		name: 'RUN_TESTS',
		script: [                 
			$class: 'GroovyScript', 
			fallbackScript: [
				classpath: [], 
				sandbox: true, 
				script: 'return ["ERROR"]'
			],                
		
		script: [       
			classpath: [], 
			sandbox: true,             
			script:""" 
				return ["YES","NO"]    
			"""        
			]             
		]],        
		[$class: 'CascadeChoiceParameter',             

		choiceType: 'PT_RADIO' ,       
		name: 'BRANCH',       
		referencedParameters: 'RUN_TESTS',                  
		script: [                 
			$class: 'GroovyScript', 
			fallbackScript: [
						classpath: [], 
						sandbox: true, 
						script: 'return ["ERROR"]'
			],                
			   
		script: [       
			classpath: [], 
			sandbox: true,             
			script:""" 
				if(RUN_TESTS.equals("YES")){
					return ["${getDummyBranches().join('","')}"]
				}else{
					return ["Disabled: Select 'Yes' to enable"]
				}    
			"""    
			]
		]] ,
		[$class: 'CascadeChoiceParameter',             
		choiceType: 'PT_CHECKBOX',     
		//choiceType: 'PT_RADIO' ,       
		name: 'MODEL_INFO',     
		referencedParameters: 'BRANCH',                 
		script: [                 
			$class: 'GroovyScript', 
			fallbackScript: [
						classpath: [], 
						sandbox: true, 
						script: 'return ["ERROR"]'
				],                
				
		script: [       
			classpath: [], 
			sandbox: true,             
			script:""" 
				if(BRANCH!=null && !BRANCH.isEmpty() && !BRANCH.contains("Disabled:")){
					return ["${getDummyModels(BRANCH).join('","')}"]
				}else{
					return ["Disabled: Select the appropriate branch above"]
				}    
			"""  ]
		]]                            
  
	]) 
])	

def getDummyBranches() {      
    return ["branch1", "branch2", "branch3"]
} 

def getDummyModels(valu) {     
    if (valu.equals("branch1")) {    
        println("inside the branch1 condition")           
        return ["model1", "model2"]     
    } else if (valu.equals("branch2")) { 
        println("inside the branch2 condition")       
        return ["model3", "model4"]    
    } else {         
        return ["model5", "model6"]     
    } 
}

node {
    stage('Print Parameters') {
			println "xxx"
	}
}

Where am I going wrong here? Or am I missing something conceptually

You have to consider that the properties of the pipeline are evaluated when the pipeline runs. So at the time when you try to select a parameter the getDummyModels method is not available but the script of that parameter has already replaced it. You would need to put the getDummyModels inside the script of parameter 3 so that the method is only called when you select the parameters.

properties([     
	parameters([  
		[$class: 'CascadeChoiceParameter',             
		choiceType: 'PT_SINGLE_SELECT',             
		name: 'RUN_TESTS',
		script: [                 
			$class: 'GroovyScript', 
			fallbackScript: [
				classpath: [], 
				sandbox: true, 
				script: 'return ["ERROR"]'
			],                
		
		script: [       
			classpath: [], 
			sandbox: true,             
			script:""" 
				return ["YES","NO"]    
			"""        
			]             
		]],        
		[$class: 'CascadeChoiceParameter',             

		choiceType: 'PT_RADIO' ,       
		name: 'BRANCH',       
		referencedParameters: 'RUN_TESTS',                  
		script: [                 
			$class: 'GroovyScript', 
			fallbackScript: [
						classpath: [], 
						sandbox: true, 
						script: 'return ["ERROR"]'
			],                
			   
		script: [       
			classpath: [], 
			sandbox: true,             
			script:""" 
				if(RUN_TESTS.equals("YES")){
					return ["${getDummyBranches().join('","')}"]
				}else{
					return ["Disabled: Select 'Yes' to enable"]
				}    
			"""    
			]
		]] ,
		[$class: 'CascadeChoiceParameter',             
		choiceType: 'PT_CHECKBOX',     
		//choiceType: 'PT_RADIO' ,       
		name: 'MODEL_INFO',     
		referencedParameters: 'BRANCH',                 
		script: [                 
			$class: 'GroovyScript', 
			fallbackScript: [
						classpath: [], 
						sandbox: true, 
						script: 'return ["ERROR"]'
				],                
				
		script: [       
			classpath: [], 
			sandbox: true,             
			script:""" 

def getDummyModels(valu) {     
    if (valu.equals("branch1")) {    
        println("inside the branch1 condition")           
        return ["model1", "model2"]     
    } else if (valu.equals("branch2")) { 
        println("inside the branch2 condition")       
        return ["model3", "model4"]    
    } else {         
        return ["model5", "model6"]     
    } 
}

				if(BRANCH!=null && !BRANCH.isEmpty() && !BRANCH.contains("Disabled:")){
					return getDummyModels(BRANCH)
				}else{
					return ["Disabled: Select the appropriate branch above"]
				}    
			"""  ]
		]]                            
  
	]) 
])	

def getDummyBranches() {      
    return ["branch1", "branch2", "branch3"]
} 


node {
    stage('Print Parameters') {
			println "xxx"
	}
}

I haven’t tested if my code is correct
the same should probably also be done for the BRANCH parameter with the the getDummyBranches method

Thank you very much. It works without the additional println commands.

However, since this parameter section gets evaluated when the pipeline runs, it should not be a problem to have a withCredential block within the script section under parameters right?

well maybe I was not 100% clear,

the block

properties([
  parameters([
  ])
])

is evaluated during a pipeline run and leads to definition of the job parameters that you can use in the next run. As you used double quotes to define the scripts string interpolation happened that lead to the execution of the method getDummyModels with the current value of branch when the pipeline was run. So when you look then at the job definition you will see that ${getDummyModels(BRANCH).join('","')} has been replaced with the return value of the method. When you now go to configure of the job will see that the
script of the MODEL_INFO parameter is now

if(BRANCH!=null && !BRANCH.isEmpty() && !BRANCH.contains("Disabled:")){
  return ["model5","model6"]
}else{
  return ["Disabled: Select the appropriate branch above"]
}

You can’t use a withCrdenetials inside the script of a parameter as this script is run when while you enter the parameters of a job before the job actually runs.

So something like this won’t work:

properties([     
	parameters([  
		[$class: 'CascadeChoiceParameter',             
		choiceType: 'PT_SINGLE_SELECT',             
		name: 'RUN_TESTS',
		script: [                 
			$class: 'GroovyScript', 
			fallbackScript: [
				classpath: [], 
				sandbox: true, 
				script: 'return ["ERROR"]'
			],                
		
		script: [       
			classpath: [], 
			sandbox: true,             
			script:""" 
                                withCredentials(...) {
                                }
				return ["YES","NO"]    
			"""        
			]             
		]],   
...
])
1 Like

Oh Okay.
But it should be possible to do so via groovy script through the com.cloudbees.plugins.credentials.SystemCredentialsProvider.getInstance().getStore().getCredentials(com.cloudbees.plugins.credentials.domains.Domain.global()) method right? Because I want to access some branches of my repository through API calls and make use of the credential inside the API call.

I tested a small script on the script console on jenkins. It worked fine.

However with the activeChoice plugin, within the script block of the parameters section, there is a failure.

properties([     
            parameters([  
                [$class: 'CascadeChoiceParameter',             
                choiceType: 'PT_SINGLE_SELECT',             
                name: 'RUN_TESTS',
                script: [                 
                    $class: 'GroovyScript', 
                    fallbackScript: [
                        classpath: [], 
                        sandbox: true, 
                        script: 'return ["ERROR"]'
                    ],                
                
                script: [       
                    classpath: [], 
                    sandbox: true,             
                    script:""" 
                        return ["YES","NO"]    
                    """        
                    ]             
                ]],        
                [$class: 'CascadeChoiceParameter',                  
                choiceType: 'PT_RADIO' ,       
                name: 'BRANCH',      
                referencedParameters: 'RUN_TESTS',                  
                script: [                 
                    $class: 'GroovyScript', 
                    fallbackScript: [
                                classpath: [], 
                                sandbox: true, 
                                script: 'return ["ERROR"]'
                    ],                
                       
                script: [       
                    classpath: [], 
                    sandbox: true,             
                    script:'''
                        import java.net.*
                        import groovy.json.*
                        def getBranches() {    
                            def PASSWORD = com.cloudbees.plugins.credentials.SystemCredentialsProvider.getInstance().getStore().getCredentials(com.cloudbees.plugins.credentials.domains.Domain.global()).
  				                          find { it.getId().equals("IMPO") }.getPassword()
                            def listOfBranches=[]
                            URL url
                            url = new URL("https://XXXXXX/branches?token=$PASSWORD")
                            response = new JsonSlurperClassic().parseText(url.getText())
                            response.each{map->
                                if (map instanceof Map){
                                    if (map.containsKey("name")){
                                        listOfBranches.add(map["name"])
                                    }
                                }

                            }
                            return listOfBranches

                        }

                        if(RUN_TESTS.equals("YES")){
                            listOfBranches =  getBranches()
                            return listOfBranches
                        }else{
                            return ["Disabled: Select 'Yes' to enable"]
                        }    
                    '''  
                    ]
                ]] ,
                [$class: 'CascadeChoiceParameter', 
                //[$class: 'ChoiceParameter',            
                choiceType: 'PT_CHECKBOX',           
                name: 'MODEL_INFO',     
                referencedParameters: 'BRANCH',                 
                script: [                 
                    $class: 'GroovyScript', 
                    fallbackScript: [
                                classpath: [], 
                                sandbox: true, 
                                script: 'return ["ERROR"]'
                        ],                
                        
                script: [       
                    classpath: [], 
                    sandbox: true,             
                    script: '''
                        import java.net.*
                        import groovy.json.*
                        def getModels(valu) {     
                             def PASSWORD = com.cloudbees.plugins.credentials.SystemCredentialsProvider.getInstance().getStore().getCredentials(com.cloudbees.plugins.credentials.domains.Domain.global()).
  				                          find { it.getId().equals("IMPO") }.getPassword()

                            url = new URL("https://XXXX/file.json?ref=$valu&token=$PASSWORD")
                            response = new JsonSlurperClassic().parseText(url.getText())

                            encoded_content= response.get('content')
                            decoded_content= new JsonSlurperClassic().parseText(new String(encoded_content.decodeBase64())) //decoding base64
                            return decoded_content.get('models-to-build')
                        }

                        if(BRANCH!=null && !BRANCH.isEmpty() && !BRANCH.contains("Disabled:")){
                            listOfModels = getModels(BRANCH)
                            return listOfModels
                        }else{
                            return ["Disabled: Select the appropriate branch above to see the test configuration"]
                        }    
                    '''  
                    ]
                ]]                            
          
            ]) 
        ])	

image

Is there any rule that I am missing out on here?

What error do you get? You have sandbox: true which will most likely prohibit that you can use things like credentials

1 Like

I modifed the sandox value for the script, I get the following response.

image

So, this portion of the code gets executed before the pipeline starts. There are no logs that get displayed actually. No error messages too

I got it working. I had to approve the script manually!

1 Like