Parametrized pipeline from SCM

Hi everyone,

I have parametrized pipeline from SCM, something like this:

parameters {
    string(name: 'VAR1', description: 'some description', trim: true)
    string(name: 'VAR2', description: 'some description', trim: true)
    string(name: 'VAR3', description: 'some description', trim: true)
<... more parameters...>
}

I don’t have default values in this Jenkinsfile, since code is in git, therefore I don’t want to keep any sensitive data there.

My idea is to populate parameters fields from Jenkinsfile on 1st build, and enter respective values in UI, so that user can change it from time to time when needed.

But generally, I would like to keep those saved parameters in UI unchanged during each build.

So far, the only solution was to populate parameters fields in UI manually, and save values there (basically by removing parameters code block from Jenkinsfile).
Because if I populate parameters from Jenkinsfile, all values from UI will disappear during next build.
I’ve even tried to comment whole parameters code block after saving parameters in UI, but after next build all is gone (parameters and values).

Is there any workaround for my idea? I wouldn’t like to generate all parameters for each project/environment manually in UI. But if that’s the only way, I’ll survive :slight_smile:

Thank you

Hello @i8z and welcome to this community :wave:

I don’t see any elegant way to do what you need to.
There’s maybe a plugin for that, but I don’t know any. :person_shrugging:

1 Like

Hi, @i8z !
You should select one place to handle job parameters: Jenkinsfile or UI.
You parameters disappear on next build because when you click Build button and build starts, it obtains Jenkinsfile from SCM, where different parameters are defined. So parameters that you’ve defined in UI has been overriden. Please note, that if you have properties block in your Jenkinsfile, that is already enough to override parameters, because parameters block is nested to properties. In this case you will receive empty parameters list.

2 Likes

Hi,
Seems like I found some partial solution for this situation on Stack Overflow:

So this:

string(name: 'parameterName', defaultValue: params.parameterName ?:'your default value')

will preserve my parameters in UI from being overwritten by default value from Jenkinsfile/SCM

And that would be exactly what I wanted, but seems like this doesn’t work with passwords as mentioned in one of the comments.

@VladyslavKovalov I’ve tried already to nest my parameters under properties. Something like this:

properties([ 
  parameters([
    string(name: 'VAR1', description: 'some description', trim: true),
    string(name: 'VAR2', description: 'some description', trim: true),
    string(name: 'VAR3', description: 'some description', trim: true),
<... more parameters...>,
    ]) 
])

… but this fails with:
The ‘properties’ section has been renamed as of version 0.8. Use ‘options’ instead

I even tried to rename properties => options, but I still end up with bunch of errors.

That’s why I gave up on properties.

I need those parameters in Jenkinsfile just to populate parameters fields in UI after first build, and then change them accordingly, because there are lot of properties there, and each project/environment has a different values there.

Really strange behavior. May be you are using declarative pipeline syntax instead of scripted pipeline. We are using Jenkins 2.387.3 LTS and properties notation works as expected. Here is the fragment of our Jenkinsfile:

properties([
    parameters([
        [$class: 'CascadeChoiceParameter',
            choiceType: 'PT_SINGLE_SELECT',
            name: 'ARTIFACT_PROJECT_NAME',
            description: "Project for copy image from",
            filterable: true,
            filterLength: 1,
            randomName: 'choice-parameter-9587366504630684',
            script: [
                $class: 'GroovyScript',
                fallbackScript: [script: 'return ["Failed to load projects"]'],
                script: [script: '''
def instances = []
for (instance in jenkins.model.Jenkins.instance.getAllItems()) {
    if (instance.getDescription() && instance.getDescription().contains("DeviceTesting")) {
        instances.add(instance.displayName)
    }
}
return instances
                '''
                ]
            ]
        ],
        [$class: 'CascadeChoiceParameter',
            choiceType: 'PT_CHECKBOX',
            description: 'Show all builds regardless its state',
            filterLength: 1,
            filterable: false,
            name: 'SHOW_FAILED_BUILDS',
            randomName: 'choice-parameter-5331064039195643',
            referencedParameters: '',
            script: [
                $class: 'GroovyScript',
                fallbackScript: [classpath: [], oldScript: '', sandbox: false, script: ''],
                script: [script: '''
return ['Show all builds']
                '''
                ]
            ]
        ],
        [$class: 'CascadeChoiceParameter',
            choiceType: 'PT_SINGLE_SELECT',
            name: 'ARTIFACT_BUILD_NUMBER',
            description: "Build number for copy image from",
            referencedParameters: 'ARTIFACT_PROJECT_NAME,SHOW_FAILED_BUILDS',
            filterable: true,
            filterLength: 1,
            randomName: 'choice-parameter-9513006304630684',
            script: [
                $class: 'GroovyScript',
                fallbackScript: [script: 'return ["Failed to load build numbers from PROJECT_NAME"]'],
                script: [script: '''
for (instance in jenkins.model.Jenkins.instance.getAllItems()) {
    if (instance.displayName == ARTIFACT_PROJECT_NAME) {
        def builds = []
        for (def build in instance.builds) {
            if (SHOW_FAILED_BUILDS == 'Show all builds') {
                builds.add(build.number)
            } else if (build.getResult().toString().equals("SUCCESS")) {
                builds.add(build.number)
            }
        }
        return builds
    }
}
                '''
                ]
            ]
        ]
    ])
])

Try to use pipeline snippet generator to generate parameters notation correctly. Pipeline snippet generator can be found by the following url pattern:
https://jenkins-url/job/pipeline_job_name/pipeline-syntax/
Here is how to do that:



1 Like

May be you are using declarative pipeline syntax instead of scripted pipeline.

Ah, that explains why it didn’t work. My pipeline has been written using declarative syntax, so it’s no wonder why parameters cannot be nested within options, especially inside ([...]). I didn’t realize until now that this syntax cannot be used in declarative pipeline.
@VladyslavKovalov thanks for brief explanation.

Running Jenkins version on this project is the latest one, 2.401.1

So basically it turns out that whole code needs to be refactored to the scripted one because of that minor detail with passwords, which sound like a really huge amount of work at this moment. Not sure if it’s worth it.

So far, code:
string(name: 'VAR1', defaultValue: params.VAR1 ?:'default value')
does exactly what I wanted to do: if there’s existing value already, don’t touch it. Othervise, provide default value.

Except the password parameter, ofc which I cannot figure out how to deal with it.
If I try something like this:
password(name: 'PW1', defaultValue: params.PW1 ?:'dummypassword')
It basically erase existing password value on first build if it finds it there. If I try a second build (when password is already erased during previous build), then it provides default value. And over and over…

Workaround for that could be to convert password to string, but then it would be visible to anyone who runs the pipeline, which is bad idea.
I’m sure that there must be a workaround for this issue.