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

Pipeline build parameters are null in first build

    XMLWordPrintable

Details

    Description

      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.

      Attachments

        Issue Links

          Activity

            sdfnanderson anderson oliveria added a comment - - edited

            Update to Critical,
            The Post-processing pipeline issue.

            sdfnanderson 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 ...

            childnode 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 ...
            abayer 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.

            abayer 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.
            mp 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}"
            mp 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}"
            felipecassiors 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.

            felipecassiors 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 .

            People

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

              Dates

                Created:
                Updated:
                Resolved: