15

I'm configuring an Android application build process with Jenkins pipeline.

At the beginning and the end of the build, a message is sent to a Slack channel. The relevant portion of the Jenkinsfile looks like so:

slackSend (channel: '#slack-test', color: 'warning', message: "Finished: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' State: ${STATE}.   Artifacts can be viewed here: ${env.BUILD_URL}artifact/Product/build/outputs/ ")

I'd also like the Slack notification to include the time it took for the build to run. Is it possible to do this without adding any external plugins?

If there's an environment variable which holds this information it would be perfect, but I can't find such a variable.

alex
  • 6,818
  • 9
  • 52
  • 103
Itai Ganot
  • 5,873
  • 18
  • 56
  • 99

4 Answers4

10

You can use ${currentBuild.durationString} to get build duration. I'm using it in my declarative pipeline scripts.

Note: If you're using HipChat plugin, you can use ${BUILD_DURATION} (previously ${DURATION}) variable in your hipchatSend command (it is propagated by the plugin with some other variables).

Example:

post {
  success {
    hipchatSend color: 'GREEN', room: 'My room', failOnError: true, notify: false, 
      message: 'Build <a href=\'${BUILD_URL}\'>${JOB_DISPLAY_NAME} #${BUILD_NUMBER}</a> has been built. Took ${BUILD_DURATION}. See the <a href=\'${BUILD_URL}/console\'>output</a>.'
  }
}

Here is some more info on Jenkins environment variables that can be used in job configuration.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
  • I'm getting the following error: ```groovy.lang.MissingPropertyException: No such property: DURATION for class: groovy.lang.Binding```. Where is `${DURATION}` defined? – EightyEight Apr 18 '18 at 18:57
  • 3
    @EightyEight I'm afraid it is specific to [HipChat plugin](https://wiki.jenkins.io/display/JENKINS/HipChat+Plugin). I've used `${currentBuild.durationString}` with other types of tasks. I guess I should reflect this in my answer.. – Vadim Kotov Apr 19 '18 at 13:38
  • 3
    If you need in number use ${currentBuild.duration}, will return in milliseconds. – rmsys Feb 11 '21 at 15:20
6

You can use ${currentBuild.durationString} to get it formatted in a human-readable format (n minutes n seconds). However it will be prefixed with and counting which is kinda weird.

So I followed this ${currentBuild.durationString.replace(' and counting', '')}

Evan Emelga
  • 81
  • 1
  • 2
3

Since this jenkins-pipeline script is in Groovy you can simply use new Date() on it. Something like this "Current time ${new Date()}" on the message argument must work:

slackSend (channel: '#slack-test', color: 'warning', message: "Current time ${new Date()}")

This will produce the follow message in your channel:

Current time: Thu Oct 13 17:25:12 CEST 2016

If you want a specific date format you can use format(String format) method, for example "${new Date().format('dd/MM/yyyy')}":

slackSend (channel: '#slack-test', color: 'warning', message: "Current time ${new Date().format('dd/MM/yyyy')}")

This instead will produce the follow message:

Current time: 13/10/2016

UPDATE

Since you don't want to use any external plugins a possible way to do so (it's a little tricky) it's to save the start time in a file using the follow script in your jenkins-pipeline:

def f = new File("/tmp/buildStart.txt")
def start = new Date().format('dd/MM/yyyy HH:mm:ss')
f.text = start
slackSend color: 'red', message: "Build start at ${start}"

Then in an other jenkins-pipeline where your build finish, parse the date from the file and get the difference with the current time:

def f = new File("/tmp/buildStart.txt")
def startDate = new Date().parse('dd/MM/yyyy HH:mm:ss',f.text)
def endDate = new Date()
def tookTime = groovy.time.TimeCategory.minus(endDate,startDate).toString()
slackSend color: 'red', message: "Total time: ${tookTime}"
albciff
  • 18,112
  • 4
  • 64
  • 89
  • I'd like like to display how long it took to run the build instead of "current time", is that possible? – Itai Ganot Oct 13 '16 at 15:40
  • @ItaiGanot ouch, sorry I misunderstood your requeriment... It's my first time using the jenkins-pipeline but I think that this must be possible saving the start time in some context variable and then subtract from the end time. I'll give you an approach. – albciff Oct 13 '16 at 15:42
  • 2
    I believe there's a more elegant way which Jenkins probably provides, but I couldn't find it myself. – Itai Ganot Oct 13 '16 at 15:52
  • @ItaiGanot - if you're okay listing ALL of the build times, you could use "${env.BUILD_URL}/job/BranchBuild/buildTimeTrend" – tkosinski Oct 13 '16 at 17:19
2

To remove the 'and counting' part from the string you can do the following:

"${currentBuild.durationString.minus(' and counting')}"

cipher0
  • 320
  • 1
  • 7