14

I am using a pipeline in a jenkinsfile and I am not sure how to properly link the job in Jenkins and the pipeline.

I defined parameters in my jenkinsfile (some with default values, some without) and have them initialized from the parameters coming from jenkins gui. The problem is that it seams the parameters in my pipeline are overiding my job parameters, EVEN when no default value is specified in the pipeline which means the pipeline is overriding my job setup in jenkins.

for example, one of my job is setup to run the pipeline with some specific values (all NON-EMPTY), if I trigger the job, the pipeline seem to reset the properties to '' for fields b and c.

How to I get the pipeline to not touch my jenkins job definition?

e.g. the params in the pipeline:

    properties([
      parameters([
        string(name: 'a',   defaultValue: 'Default A value', description: '', ),
        string(name: 'b',   description: '', ),
        string(name: 'c',   description: '', ),
       ])
])

I am not find any help in the documentation at https://jenkins.io/doc/book/pipeline/syntax/#parameters-example

StephenKing
  • 36,187
  • 11
  • 83
  • 112
NicolasW
  • 1,519
  • 5
  • 22
  • 34
  • 1
    I gave up on the pipelines for now, it has too many aspects undocumented, many designs such as params management are very hard to work with, create too much code duplication, etc. You'd think the added value of pipelines is testability, simplicity but since you cannot test or execute locally pipelines you end up spending much time clicking again and again in the interface, so there is not much added value compared to the traditional jobs (these appear more mature). – NicolasW May 07 '18 at 20:34

3 Answers3

18

Ah, yes, it got me the first time around also.

The first time that you run the pipeline, the jenkinsFile DSL job definition pretty much overrides the whole job definition that you have entered thru the GUI. That affects the parameters in particular.

So make sure you define the parameters exactly how you want them in the Jenkinsfile, then run the job once, and the GUI will have the same config for the parameters, so that when you run again, it will ask for the parameters and use the default values, that you specified in the DSL. There is nothing more to it.

Yes, having to run twice everytime you modify the parameters in the DSL is annoying. But it sort of makes sense if you consider that the job has to execute for the DSL to be evaluated, but first it needs to ask for parameters if you have some defined via the UI, BEFORE it checks out and evaluates the DSL...

Patrice M.
  • 4,209
  • 2
  • 27
  • 36
  • 1
    Thx Patrice, however I really can t afford having the parameters in the pipeline because it is shared across multiple projects.. – NicolasW Jun 10 '17 at 15:18
  • But I'm saying that you can't have parameters in the pipeline job that won't be reset by the jenkinsfile when you run it the first time. So for you scenario to work, you'd have to have a single 'main' job with the jenkinsfile, and then additional starter (freestyle) jobs that provide defaults, and will simply kick off the main job and pass the specific parameter values. Alternatively, your pipeline DSL could have some logic to compute different parameters default values, based on context. But that would be fairly restricted I suppose. – Patrice M. Jun 10 '17 at 15:45
  • Hi Patrice, sounds great, are you implying I should be using the Parameterized Trigger Plugin so I can run a build from another build? I found the freestyle build type but when running other builds from there noticed my params were not passed. I did not know about this option and today realized it was part of a plugin.. imo this should be part of the base version of Jenkins! – NicolasW Jun 12 '17 at 19:08
  • 1
    You can use the freestle project type with that plugin, or use a Jenkins 2 jenkinsfile as well, such as: build job: jobName, parameters: [ stringParam (name: 'a', value: 'Default A value') ] – Patrice M. Jun 12 '17 at 20:34
  • Any clues how to get the build status visible in the freestyle build? I m new at Jenkins and come from Teamcity, I am really having a hard time finding up-to-date detailed documentation on Jenkins features. – NicolasW Jun 13 '17 at 14:25
  • solved - found my issue, was using post build action and had to use build action to be able to use the return code. – NicolasW Jun 13 '17 at 14:36
  • Hopefully my last comment - the problem I am seeing with the freestyle project calling my pipeline is that my logs are not visible in the freestyle project, this will be very confusing for end-users.. as all logs end up in the jenkinsfile project.. not the freestyle. Maybe I missed sth ? Your second suggestion about adding another Jenkinsfile to make the call sounds like an overkill as I end up with multiple jenkinsfile. – NicolasW Jun 13 '17 at 21:06
  • new question at https://stackoverflow.com/questions/44532076/multiple-projects-sharing-a-jenkinsfile with detailed requirements (including logs!) and including the above suggestions. I am still having a hard time understanding how is this making sense for the jenkinsfile to override my job parameters, especially if there are no default value for that param in its definition. – NicolasW Jun 13 '17 at 21:52
  • 1
    Thank you for accepting the answer. Again, the ability to define parameters for a job in the UI, is a complete illusion. The jenkinsfile will override this as soon as it is loaded from SCM and evaluated, not just in the job runtime, but also in the job definition (it will rewrite the whole job configuration). It will delete parameters that are not present in the jenkinsFile, and change or erase the default values to match the DSL. So the only way to have multiple jobs sharing the same jenkinsFile is to have a set of jobs in front of it with specific parameter values (default or hard-coded) – Patrice M. Jun 14 '17 at 05:06
  • Now, w.r.t. the log of your downstream project being pulled into the upstream console log, maybe this other question can help you: https://stackoverflow.com/questions/24176033/how-to-get-jenkins-console-output-after-triggering-build-remotely – Patrice M. Jun 14 '17 at 05:10
  • Sounds like it would work, but also like a hack. One more thing we would miss with freestyle jobs calling the pipeline job (using Parameterized Trigger Plugin ) is the stage view with the execution steps, time to executed, check-ins. so I don t think this is a viable solution. – NicolasW Jun 14 '17 at 14:29
3

This problem can be solved by adding a special parameter to avoid default values being override. Here is the sample code.

if (!params.__INIT__) { // this value will be true once parameters get initialized
    properties([ parameters([
            string(name: 'SOURCE_URL', trim: true),
            string(name: 'TARGET_URL', trim: true),

            string(name: 'DEPLOY_URL', trim: true),
            credentials(name: 'DEPLOY_KEY', required: true ),

            string(name: 'BUILD_NODE', trim: true),

            booleanParam(name: '__INIT__', defaultValue: true, description: "Uncheck this field in configuration page and run this job once if you want to re init parameter."),
    ]) ])
    return // exit 
}

// Your task stars from here

By doing this way, the parameters won't be initialized again next time because __INIT__ has been set to true. On the other hand, if you update your script and change some parameters, you can just run the job by unchecking the __INIT__ field.

link89
  • 1,064
  • 10
  • 13
  • @link89 is it possible with declarative pipeline? – Andrey Ershov Sep 09 '21 at 06:02
  • I don't think this workaround can be used with declarative pipeline directly as you cannot control its execution flow. – link89 Sep 10 '21 at 02:24
  • I think you can. Just omit pipeline { parameters } and and the above code before { pipeline } – felipecrs Dec 09 '21 at 15:35
  • Nice one, this is really underrated solution, I either imagine using this or have a folder for a pipeline per environment so basically copies of same pipeline with diff params in order to have everything tracked, the triggered pipeline approach looks like something different to me. – anVzdGFub3RoZXJodW1hbg Jun 10 '22 at 15:19
0

Old question, and there are maybe some better solutions now, but I didn't find them, so posting this anyway in case it helps.
@link69 answer is really good, and led me to something maybe a bit more advanced,
which allows choosing whereas a user provided value is stored or not as the default value.
On my side, there are parameters that I would like to be "one shot", eg "debug build", while I would like to be able to set some persistent parameters from the UI (eg git branch to be used).
The main drawback is that the pipeline doesn't know if a parameter has been modified from the project "configure" page or in "build with parameters", and saves the value as "default" in both cases. I also don't like to repeat the parameter name twice for each parameter in the parameters block.

// Update parameters[paramName] with defaultValue if paramName key is not present,
// Return the default value
def <T> T updateMapReturnDefault(Map parameters, String paramName, T defaultValue)
{
    if (!parameters.containsKey(paramName))
        parameters[paramName] = defaultValue

    return defaultValue
}

// Update parameters[paramName] with defaultValue if paramName key is not present,
// Return the value read from the map if present, the default value otherwise
def <T> T updateMapReturnValue(Map parameters, String paramName, T defaultValue)
{
    if (!parameters.containsKey(paramName))
        parameters[paramName] = defaultValue

    return parameters[paramName]
}

def call(Map config) {
    node {
        // Copy params map to allow modifying it
        userParams = new HashMap(params)

        properties([
            parameters([
                // Value will be stored as default on each build
                string(name: "GIT_BRANCH", defaultValue: updateMapReturnValue(userParams, "GIT_BRANCH", "main")),
                // Value will be reset on each build
                booleanParam(name: "DEBUG_BUILD", defaultValue: updateMapReturnDefault(userParams, "DEBUG_BUILD", false)),
                // Set JUST_UPDATE_PARAMETERS to true to update the parameters list and exit
                // True by default so that the first build just updates the parameters
                booleanParam(name: "JUST_UPDATE_PARAMETERS", defaultValue: updateMapReturnValue(userParams, "JUST_UPDATE_PARAMETERS", true)),
            ])
        ])

        if (userParams.JUST_UPDATE_PARAMETERS) {
            stage("Update pipeline parameters") {
                println("JUST_UPDATE_PARAMETERS is set, not building")
                currentBuild.displayName = "parameters update"
                return
            }
        }

        stage("build") {
            println("Build started, branch ${userParams.GIT_BRANCH}, debug_build: ${userParams.DEBUG_BUILD}")
        }
    }
}
Bouloche
  • 36
  • 4
  • If you have a new question, please ask it by clicking the [Ask Question](https://stackoverflow.com/questions/ask) button. Include a link to this question if it helps provide context. - [From Review](/review/late-answers/34452004) – mfg3z0 May 31 '23 at 17:48