0

I have a pipeline which I just added 2 parameters to build release or debug (parameters are called release or debug). The pipeline uses cron syntax to check for changes in the SCM every 10 mins, the pipeline checks for every commit and then build release (C++ program) but I would like to build debug once a day, let's say everyday every coomit pushed from 12 to 13 will be build in debug. All of this without me having to run the pipeline and changing the parameter manually (it is set to release by default). Is there any way to do this? This is a very short version of what the pipeline looks like:

    pipeline {
    
        stages {
          stage('Setup parameters') {
            steps {
                script { 
                    properties([
                        parameters([
                            choice(
                                defaultValue: 'RELEASE', 
                                choices: ['RELEASE', 'DEBUG'], 
                                name: 'BUILD_CONFIG'
                            ),
                        ])
                    ])
                }
            }
        }
        stage('Build release'){
            when {
                expression {
                   return params.BUILD_CONFIG == 'RELEASE'
                }
            }
            steps{
                script {
                    def msbuild = tool name: 'MSBuild', type: 'hudson.plugins.msbuild.MsBuildInstallation'
                    bat "\"${msbuild}\" /Source/project-GRDK.sln /t:Rebuild  /p:configuration=\"Release Steam D3D11\""
                }
            }
        }
        stage('Build debug'){
            when {
                expression {
                   return params.BUILD_CONFIG == 'DEBUG'
                }
            }
            steps{
                script {
                    def msbuild = tool name: 'MSBuild', type: 'hudson.plugins.msbuild.MsBuildInstallation'
                    bat "\"${msbuild}\" /Source/project-GRDK.sln /t:Rebuild /p:configuration=\"Debug Steam D3D11\""
                }
            }
        }
        }
    }
Jesus Fernandez
  • 500
  • 1
  • 7
  • 20

3 Answers3

2

It is possible to determine the cause of the build with currentBuild.rawBuild.getCause(Class<T> type). The type you are looking for is UserIdCause. Following would build a stage in case the job was not triggered by an user (manually). In this stage steps are from Build debug stage.

stage('Build debug if time triggered') {
   when {
     expression {
       return currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause) == null
     }
   }
   steps {
     script {
       def msbuild = tool name: 'MSBuild', type: 'hudson.plugins.msbuild.MsBuildInstallation'
       bat "\"${msbuild}\" /Source/project-GRDK.sln /t:Rebuild /p:configuration=\"Debug Steam D3D11\""
            
     }
}

You will also need to add an expression to Build release and Build debug stages, in order to prevent building if the job is not triggered by an user (manually).

    stage('Build release'){
        when {
            allOf {
               expression {
                   return params.BUILD_CONFIG == 'RELEASE'
               }
               expression {
                   return currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause) != null
               }
            }
        }
        ...

Docu:
https://javadoc.jenkins-ci.org/hudson/model/Cause.html
https://javadoc.jenkins-ci.org/hudson/model/Run.html
How to differentiate build triggers in Jenkins Pipeline

EDIT
If you want to keep everything in one pipeline, then you need to create two new variables. Following code creates Calendar object for 12 am today and converts it to milliseconds.

Calendar date = new GregorianCalendar()
date.set(Calendar.HOUR_OF_DAY, 12);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);

def start = date.getTime().getTime()

In same way you could create a Calendar object for 1 pm today (e.g. end). With currentBuild.rawBuild.getTimestamp() you get Calendar object, when the build was scheduled. If the scheduled time is between start and end set for example a boolean variable and check it in the pipeline when block.

def buildDebug = false
def scheduled = currentBuild.rawBuild.getTimestamp().getTime().getTime()
if(scheduled > start && scheduled < end)
  buildDebug = true

...

stage('Build release'){
  when {
    allOf {
      expression {
        return params.BUILD_CONFIG == 'RELEASE'
      }
      expression {
        return currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause) == null
      }
      expression {
        return buildDebug == false
      }
    }
  }
  ...
stage('Build debug'){
  when {
    allOf {
      expression {
        return params.BUILD_CONFIG == 'RELEASE'
      }
      expression {
        return currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause) == null
      }
      expression {
        return buildDebug == true
      }
    }
  }
  
 

How to create a Java Date object of midnight today and midnight tomorrow?

Melkjot
  • 498
  • 3
  • 13
  • but this will just make a difference between being triggered manually and being triggered by cron, what I would like to achieve is to always be triggered by cron and build release except if is triggered between 12 -13 for instance. @Melkjot – Jesus Fernandez Sep 22 '21 at 10:08
  • @JesusFernandez I've edited my answer, added how can you determine if the build was triggered by cron between 12-13. – Melkjot Sep 22 '21 at 12:47
2

Another option would be to create a second job, which triggers the build job with the right parameters:

pipeline {
   agent any

   triggers {
       cron('H 12 * * *')
   }

   stages {
       stage('Build xxx debug') {
           steps {
               build job: "your-job-name-here", parameters: [
                   choice(name: 'BUILD_CONFIG', value: 'DEBUG')
               ]
           }
       }
   }
}
crash
  • 603
  • 4
  • 11
  • thanks for your reply, I thought about that but I would prefer to keep it on the same pipeline and therefore the same WS – Jesus Fernandez Sep 22 '21 at 11:03
  • ok I see now what you mean, I got it wrong at first look, so basically this will call the job posted above and will pass the parameter to build debug, which I do not see clearly is how the parameters choice block works as I have no used it before, is there any documenation on jenkins site about this? – Jesus Fernandez Sep 22 '21 at 11:46
  • [Documentation for build parameters](https://www.jenkins.io/doc/book/pipeline/syntax/#parameters) and [for pipeline build step (and following)](https://www.jenkins.io/doc/pipeline/steps/pipeline-build-step/) There are more parameters available, which are undocumented. And btw you could also try this plugin: https://plugins.jenkins.io/parameterized-trigger/ – crash Sep 22 '21 at 12:56
2

parameterizedCron plugin does what you need:

pipeline {
    agent any
    parameters {
        choice(name: 'BUILD_CONFIG', choices: ['RELEASE', 'DEBUG'], defaultValue: 'RELEASE')
    }
    triggers {
        parameterizedCron('''
            1,2,3,4,5,6,7,8,9,10 * * * * % BUILD_CONFIG=RELEASE
            12 * * * * % BUILD_CONFIG=DEBUG
        ''')
    }
MaratC
  • 6,418
  • 2
  • 20
  • 27