Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-40574

Pipeline build parameters are null in first build

      Parameters which are set in properties in a pipeline build are null the first time the build is run, even if they are given default values. On subsequent builds, the parameters have values as expected.

      Example: create a new Pipeline job and define the pipeline script like this in the build config:

      properties([
        [$class: 'ParametersDefinitionProperty',
          parameterDefinitions: [
            [$class: 'StringParameterDefinition',
              name: 'SOME_PARAMETER',
              defaultValue: 'some value',
              description: 'A test parameter']]
        ]
      ])
      
      echo "Value of parameter:"
      echo env.SOME_PARAMETER
      

      Run the build by clicking "Build" (note that this says "Build" rather than "Build with Parameters" unless the build has been run at least once). The console output is:

      [Pipeline] echo
      Value of parameter:
      [Pipeline] echo
      null
      

      Run the build a second time by clicking "Build with Parameters" and then confirming the default value. The console output is now:

      [Pipeline] echo
      Value of parameter:
      [Pipeline] echo
      some value
      

      If you refer to the parameter directly using SOME_PARAMETER rather than env.SOME_PARAMETER, the first build fails with a groovy.lang.MissingPropertyException instead.

      This isn't so bad when you're configuring a single new job, but it becomes a real problem for multibranch pipeline jobs, because the first build of every branch always fails unless the pipeline script does extra work to handle the missing parameter.

          [JENKINS-40574] Pipeline build parameters are null in first build

          Suzanne Hamilton added a comment - This StackOverflow question seems to be referring to the same issue: http://stackoverflow.com/questions/40782302/jenkinsfile-parameter-properties-not-configured-in-jenkins-server-at-initial-bra

          Paul LeTang added a comment -

          You can get around this by using params.SOME_PARAMETER instead of env.SOME_PARAMETER.

          Paul LeTang added a comment - You can get around this by using params.SOME_PARAMETER instead of env.SOME_PARAMETER.

          Glib Briia added a comment -

          Tried using params.SOME_PARAMETER, no exception is thrown but parameter value is passed as 'null'. 

          As mentioned above this causing all initial builds to fail in multi branch pipelines configuration with automatic pipelines creation for new branches or pull requests. Bumping priority.

           

          Glib Briia added a comment - Tried using params.SOME_PARAMETER, no exception is thrown but parameter value is passed as 'null'.  As mentioned above this causing all initial builds to fail in multi branch pipelines configuration with automatic pipelines creation for new branches or pull requests. Bumping priority.  

          anderson oliveria added a comment - - edited

          Hello, from Rio BRZ.

          The jenkins pipeline parameters are post-processed. This is a issue.

          Maybe the assignee can implement some sort of "constructor node" and use a two step process pipeline:
          filtering the first of "constructors node" and the pipeline parameters. Next, show the user interface, with the parameters set. At last, execute the pipeline.

          One sample of the "constructor example model", with preprocessing pipeline:
          --------------------------------------------------------------------
          import groovy.json.JsonSlurperClassic
          import java.text.SimpleDateFormat

          @NonCPS
          def jsonParse(def json) {
          new groovy.json.JsonSlurperClassic().parseText(json)
          }

          // Some static parameter ...
          def stringS="Start new VM"

          __node { //The Constructor Node idea...
          sh 'cat /var/lib/libvirt/dnsmasq/virbr0.status'

          def props = readFile file: '/var/lib/libvirt/dnsmasq/virbr0.status'
          def jsonProps = jsonParse(props)

          def params = jsonProps

          params.each

          { println it."ip-address" stringS = stringS+"\n"+it."ip-address" }

          println stringS
          }

          pipeline {

          agent any

          parameters

          { choice(choices: stringS, description: 'Opcoes de Comando para Ligar Maquina Virtual ou Desligar Maquina Virtual', name: 'VMCOMMAND') choice(choices: 'Do nothing\nSet Database\nStart interc2\nStop interc2', description: 'Opcoes de Comando para Ligar Maquina Virtual ou Desligar Maquina Virtual', name: 'VMARGS1') }

          anderson oliveria added a comment - - edited Hello, from Rio BRZ. The jenkins pipeline parameters are post-processed. This is a issue. Maybe the assignee can implement some sort of "constructor node" and use a two step process pipeline: filtering the first of "constructors node" and the pipeline parameters. Next, show the user interface, with the parameters set. At last, execute the pipeline. One sample of the "constructor example model", with preprocessing pipeline: -------------------------------------------------------------------- import groovy.json.JsonSlurperClassic import java.text.SimpleDateFormat @NonCPS def jsonParse(def json) { new groovy.json.JsonSlurperClassic().parseText(json) } // Some static parameter ... def stringS="Start new VM" __node { //The Constructor Node idea... sh 'cat /var/lib/libvirt/dnsmasq/virbr0.status' def props = readFile file: '/var/lib/libvirt/dnsmasq/virbr0.status' def jsonProps = jsonParse(props) def params = jsonProps params.each { println it."ip-address" stringS = stringS+"\n"+it."ip-address" } println stringS } pipeline { agent any parameters { choice(choices: stringS, description: 'Opcoes de Comando para Ligar Maquina Virtual ou Desligar Maquina Virtual', name: 'VMCOMMAND') choice(choices: 'Do nothing\nSet Database\nStart interc2\nStop interc2', description: 'Opcoes de Comando para Ligar Maquina Virtual ou Desligar Maquina Virtual', name: 'VMARGS1') }

          anderson oliveria added a comment - - edited

          Update to Critical,
          The Post-processing pipeline issue.

          anderson oliveria added a comment - - edited Update to Critical, The Post-processing pipeline issue.

          You can get around this by using params.SOME_PARAMETER instead of env.SOME_PARAMETER.

          igycrctl: this doesn't even work for older Pipelines due to

          groovy.lang.MissingPropertyException: No such property: params for class: groovy.lang.Binding
          

          my actual messy workaround:

          def defaults = [:]
          defaults['testParam'] = 'test'
          defaults['testParam2'] = 'test2'
          defaults['anything'] = 'foobar'
          
          def testParam = env.testParam == null ? defaults['testParam'] : env.testParam,
              testParam2 = env.testParam2 == null ? defaults['testParam2'] : env.testParam2,
              anything = env.anything == null ? defaults['anything'] : env.anything
              
          properties([
              [
                  $class: 'ParametersDefinitionProperty',
                  parameterDefinitions: [
                      [
                          $class      : 'StringParameterDefinition',
                          name        : 'testParam',
                          defaultValue: testParam,
                          required    : true
                      ],
                      [
                          $class      : 'StringParameterDefinition',
                          name        : 'testParam2',
                          defaultValue: testParam2,
                          required    : true
                      ],
                      [
                          $class      : 'StringParameterDefinition',
                          name        : 'anything',
                          defaultValue: anything,
                          required    : false
                      ],
                  ]
              ]
          ])
          assert testParam.trim() != "" : "testParam not defined"
          assert testParam2.trim() != "" : "testParam2 not defined"
          
          node {
              echo "testParam: ${testParam}"
              echo "testParam2: ${testParam2}"
              echo "anything: ${anything}"
          }
          

          with the "drawback" that defined defaults only written once if they are not defined but any build changes the default value in job configuration. Although this enables to change the default values manually in job definition for future builds ...

          Marcel 'childNo͡.de' Trautwein added a comment - - edited You can get around this by using params.SOME_PARAMETER instead of env.SOME_PARAMETER. igycrctl : this doesn't even work for older Pipelines due to groovy.lang.MissingPropertyException: No such property: params for class: groovy.lang.Binding my actual messy workaround: def defaults = [:] defaults[ 'testParam' ] = 'test' defaults[ 'testParam2' ] = 'test2' defaults[ 'anything' ] = 'foobar' def testParam = env.testParam == null ? defaults[ 'testParam' ] : env.testParam, testParam2 = env.testParam2 == null ? defaults[ 'testParam2' ] : env.testParam2, anything = env.anything == null ? defaults[ 'anything' ] : env.anything properties([ [ $class: 'ParametersDefinitionProperty' , parameterDefinitions: [ [ $class : 'StringParameterDefinition' , name : 'testParam' , defaultValue: testParam, required : true ], [ $class : 'StringParameterDefinition' , name : 'testParam2' , defaultValue: testParam2, required : true ], [ $class : 'StringParameterDefinition' , name : 'anything' , defaultValue: anything, required : false ], ] ] ]) assert testParam.trim() != "" : " testParam not defined" assert testParam2.trim() != "" : " testParam2 not defined" node { echo "testParam: ${testParam}" echo "testParam2: ${testParam2}" echo "anything: ${anything}" } with the "drawback" that defined defaults only written once if they are not defined but any build changes the default value in job configuration. Although this enables to change the default values manually in job definition for future builds ...

          Andrew Bayer added a comment -

          Yeah, in modern versions of Pipeline, you've got params.SOME_PARAMETER, which will be defined to its default value on the first run (once you've run the properties step in Scripted Pipeline - in Declarative, we process that before anything else happens). We're still looking for the right way to populate those parameters before the first build for Declarative Pipelines over in JENKINS-41929, but no answer there yet.

          Andrew Bayer added a comment - Yeah, in modern versions of Pipeline, you've got params.SOME_PARAMETER , which will be defined to its default value on the first run (once you've run the properties step in Scripted Pipeline - in Declarative, we process that before anything else happens). We're still looking for the right way to populate those parameters before the first build for Declarative Pipelines over in JENKINS-41929 , but no answer there yet.

          M P added a comment - - edited

          The workaround that we're currently using is to simply map all parameters to environment variables after the parameters block explicitly:

          properties([
              parameters([
                  string(name: "FOO", defaultValue: "bar"),
              ])
          ])
          params.each { k, v -> env[k] = v }
          
          echo "FOO=${env.FOO}"

          M P added a comment - - edited The workaround that we're currently using is to simply map all parameters to environment variables after the parameters block explicitly: properties([ parameters([ string(name: "FOO" , defaultValue: "bar" ), ]) ]) params.each { k, v -> env[k] = v } echo "FOO=${env.FOO}"

          Felipe Santos added a comment -

          This is my suggestion:

          stage('Preparations') {
            steps {
              echo 'Initialize parameters as environment variables due to https://issues.jenkins-ci.org/browse/JENKINS-41929'
              evaluate """${def script = ""; params.each { k, v -> script += "env.${k} = '''${v}'''\n" }; return script}"""
            }
          }
          

          From https://issues.jenkins.io/browse/JENKINS-41929?focusedCommentId=399590&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-399590.

          Felipe Santos added a comment - This is my suggestion: stage( 'Preparations' ) {   steps {     echo  'Initialize parameters  as  environment variables due to https: //issues.jenkins-ci.org/browse/JENKINS-41929'     evaluate """${ def script = " "; params.each { k, v -> script += " env.${k} = '''${v}' ''\n " }; return script}" ""   } } From https://issues.jenkins.io/browse/JENKINS-41929?focusedCommentId=399590&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-399590 .

            Unassigned Unassigned
            suzannehamilton Suzanne Hamilton
            Votes:
            9 Vote for this issue
            Watchers:
            17 Start watching this issue

              Created:
              Updated:
              Resolved: