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

Offer "Build with Parameters" on first build when declarative Jenkinsfile found

    XMLWordPrintable

    Details

    • Similar Issues:

      Description

      By default a branch project will automatically run the first build, with no parameters, so params will just pick up any default values. You have the option to suppress the automatic first build, but this does not give you any way to enter parameters for it (at least in the UI; perhaps possible via CLI/REST), since Jenkins does not know what the parameters are going to be until it starts running. But in the case of Declarative we could in principle inspect the Jenkinsfile when the branch project is created (via SCMFileSystem) and determine the parameter definitions by static parsing without actually running.

      More generally, if Declarative is in use and there are properties, we could set all the project properties when the branch project is created, even if the first build is run automatically. (Though I would suggest that the automatic first build should be automatically suppressed if there is a ParametersDefinitionProperty.)

        Attachments

          Issue Links

            Activity

            Hide
            ifernandezcalvo Ivan Fernandez Calvo added a comment - - edited

            We have other workaround for those builds do not have default values on all parameters, and they need values, we mark the build as not build at when level and we skip everything, to do that we check that the environment variable and the parameter has the same value, we also check that the mandatory parameters has value.

            stage('Prepare') {
              when {
                expression {
                  def ret = (
                    "${env.PARAM01}" == "${params.PARAM01}"
                    && "${params.PARAM01}" != ""
                    && "${params.PARAM02}" != ""
                    && "${params.PARAM03}" != ""
                    )
                  if(!ret){
                    currentBuild.result = 'NOT_BUILT'
                    currentBuild.description = "The build has been skipped"
                    currentBuild.displayName = "#${BUILD_NUMBER}-(Skipped)"
                    echo("This build does not have valid parameters.")
                  }
                  return ret
                }
              }
              stages {
                stage('checkout'){
                  ....
                }
                stage('lint'){
                  ....
                }
                stage('build'){
                  ....
                }
                stage('test'){
                  ....
                }
              }
            }
            
            Show
            ifernandezcalvo Ivan Fernandez Calvo added a comment - - edited We have other workaround for those builds do not have default values on all parameters, and they need values, we mark the build as not build at when level and we skip everything, to do that we check that the environment variable and the parameter has the same value, we also check that the mandatory parameters has value. stage( 'Prepare' ) { when { expression { def ret = ( "${env.PARAM01}" == "${params.PARAM01}" && "${params.PARAM01}" != "" && "${params.PARAM02}" != "" && "${params.PARAM03}" != "" ) if (!ret){ currentBuild.result = 'NOT_BUILT' currentBuild.description = "The build has been skipped" currentBuild.displayName = "#${BUILD_NUMBER}-(Skipped)" echo( "This build does not have valid parameters." ) } return ret } } stages { stage( 'checkout' ){ .... } stage( 'lint' ){ .... } stage( 'build' ){ .... } stage( 'test' ){ .... } } }
            Hide
            felipecassiors Felipe Santos added a comment - - edited

            I think that's not similar... you don't fix the environment variables, you skip the build if they're not fixed.

            The workaround I proposed actually fixes the environment variables to point to the defaultValue of the parameters, so you don't need to skip the build.

            Show
            felipecassiors Felipe Santos added a comment - - edited I think that's not similar... you don't fix the environment variables, you skip the build if they're not fixed. The workaround I proposed actually fixes the environment variables to point to the defaultValue of the parameters, so you don't need to skip the build.
            Hide
            timblaktu Tim Black added a comment - - edited

            We have implemented a workaround to the core problem, similar to Michael Brunner's above, and it's been working well for some months, but now we're interested in making this a bit more seamless, and less confusing, for our users. (We can't expect all software developers using a Jenkin-based build system to know all of Jenkins' quirks, and this, IMO, is one of Jenkins' worst dirty little secrets.)

            So far, what we've done is add this first stage to our pipeline:

                    stage("Loading Parameters on First Build") {
                        when { expression { env.BUILD_NUMBER == '1' } }
                        // Because this: https://issues.jenkins-ci.org/browse/JENKINS-41929
                        steps {
                            script {
                                if (currentBuild.getBuildCauses('hudson.model.Cause$UserIdCause') != null) {
                                    currentBuild.displayName = 'Parameter Initialization'
                                    currentBuild.description = 'On first build we just load the parameters as they are not available of first run on new branches.  A second run has been triggered automatically.'
                                    currentBuild.result = 'ABORTED'
                                  
                                  	// Re-run this job (correct any /'s) but don't wait...
                                  	build job: env.BRANCH_NAME.replace("/","%2F"), wait: false
                                  
                                    error('Stopping initial manually-triggered build as we only want to get the parameters')
                                }
                            }
                        }
                    }
            

            Automatically triggering build #2 helps, but this approach has 2 problems:

            1. it's still kind of confusing to users what happened in build #1 and why it was necessary
            2. we use Jenkins Build # in our semantic versioning scheme, so there can never be a Version a.b.c.1. Versions always start with a.b.c.2.

            From my perspective, Jobs that have params defined in Pipeline, Build #1 can always be thrown away. So, my new workaround proposal, which may or may not be applied to any real solution under-Jenkins'-hood, is to modify the above stage to delete Build #1 (from disk) and set the next build number to 1 before triggering itself again.

            I haven't implemented/tested this myself yet, but wanted to ask here: can this be done safely? I'm not using the Next Build Number plugin, and don't plan to, because _complexity _and to my knowledge it can only handle monotonically increasing build numbers. I'm thinking something along these lines in a script {} block:

            def job = Jenkins.instance.getItem(jobName)
            job.getBuild(1).delete()  # how dangerous is this? Would it be better/worse to just delete jobs/jobName/builds/1 on disk?? Why?
            job.nextBuildNumber = 1
            

            Thanks for your time..

            Show
            timblaktu Tim Black added a comment - - edited We have implemented a workaround to the core problem, similar to Michael Brunner 's above, and it's been working well for some months, but now we're interested in making this a bit more seamless, and less confusing , for our users. (We can't expect all software developers using a Jenkin-based build system to know all of Jenkins' quirks, and this, IMO, is one of Jenkins' worst dirty little secrets.) So far, what we've done is add this first stage to our pipeline: stage( "Loading Parameters on First Build" ) { when { expression { env.BUILD_NUMBER == '1' } } // Because this : https://issues.jenkins-ci.org/browse/JENKINS-41929 steps { script { if (currentBuild.getBuildCauses( 'hudson.model.Cause$UserIdCause' ) != null ) { currentBuild.displayName = 'Parameter Initialization' currentBuild.description = 'On first build we just load the parameters as they are not available of first run on new branches. A second run has been triggered automatically.' currentBuild.result = 'ABORTED' // Re-run this job (correct any / 's) but don' t wait... build job: env.BRANCH_NAME.replace( "/" , "%2F" ), wait: false error( 'Stopping initial manually-triggered build as we only want to get the parameters' ) } } } } Automatically triggering build #2 helps, but this approach has 2 problems: it's still kind of confusing to users what happened in build #1 and why it was necessary we use Jenkins Build # in our semantic versioning scheme, so there can never be a Version a.b.c.1. Versions always start with a.b.c.2. From my perspective, Jobs that have params defined in Pipeline, Build #1 can always be thrown away . So, my new workaround proposal, which may or may not be applied to any real solution under-Jenkins'-hood, is to modify the above stage to delete Build #1 (from disk) and set the next build number to 1 before triggering itself again . I haven't implemented/tested this myself yet, but wanted to ask here: can this be done safely? I'm not using the Next Build Number plugin, and don't plan to, because _complexity _and to my knowledge it can only handle monotonically increasing build numbers. I'm thinking something along these lines in a script {} block: def job = Jenkins.instance.getItem(jobName) job.getBuild(1).delete() # how dangerous is this ? Would it be better/worse to just delete jobs/jobName/builds/1 on disk?? Why? job.nextBuildNumber = 1 Thanks for your time..
            Hide
            felipecassiors Felipe Santos added a comment -

            Tim Black, does not my suggestion solves your problem?

            Show
            felipecassiors Felipe Santos added a comment - Tim Black , does not my suggestion solves your problem?
            Hide
            timblaktu Tim Black added a comment -

            Felipe Santos I like your slick 2-liner solution. I'm just not yet convinced that I'm ready to switch paradigms from using params to using environment variables in my pipelines.

            Show
            timblaktu Tim Black added a comment - Felipe Santos I like your slick 2-liner solution. I'm just not yet convinced that I'm ready to switch paradigms from using params to using environment variables in my pipelines.

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              jglick Jesse Glick
              Votes:
              132 Vote for this issue
              Watchers:
              144 Start watching this issue

                Dates

                Created:
                Updated: