5

Is there a way in Groovy directly or by integrating Jenkins plugins to have a downstream job complete only if it hasn't been run in the last X hours already?

Let's say I have unit tests, when green, kick off a job to create an image. I want to put an intermediary step between the two that will check to see when the last iteration of the image creation job ran, and if it was less than say 3 hours ago, NOT run the image creation job.

There isn't a way to make this work with cron that I can see, since the upstream job runs at random whenever commits are made, obfuscating any timing control. I can't just schedule the image creation because sometimes we get 10+ commits in an hour, and sometimes there's barely one a day. When that single one of the day does turn green I'd rather immediately create an image for use downstream, rather than waiting as much as 3 hours if I schedule it.

I'd prefer not to make it a 1:1 ratio commit to image only because storing them gets tricky in large numbers, and downstream from the image you'd never need them as frequently as the aforementioned 10 per hour.

3 Answers 3

4

To synthesize Alex and Steve Johnson's answers, you could put this at the top of your downstream job:

lastBuild = currentBuild.getPreviousBuild()
delay = 2

if Date(lastBuild.timestamp) >= new Date().minusHours(delay) {
    currentBuild.result = 'SUCCESS'
    echo "Less than ${delay} hours since the last build. Job will not run."
    return
}
2
  • Valid, but only if you don't want to be able to kick off the downstream job manually. To be fair though I didn't mention that as a requirement, so your answer would be correct in that scenario!
    – Alex
    Commented May 4, 2017 at 15:57
  • 1
    Absolutely, I think your solution is the best way forward. I just thought of a way to improve upon Steve's with part of your solution. I was just going to comment on his, but the code formatting didn't work. Commented May 4, 2017 at 16:00
2

Took a while and it's a little on the hacky side since I'm no Groovy expert, but I got it working with this;

long now = System.currentTimeMillis()

node('jenkins2_dedicated_slave'){

    stage ('check time') {

        sh '''lastBuild=$(mktemp)

        curl -u [jenkins username]:[API key for user] "http://[jenkins URL]/[job name]/lastSuccessfulBuild/api/json" > $lastBuild

        jq -j '.timestamp' < $lastBuild > time.txt'''

    }

    archiveArtifacts artifacts: 'time.txt'
    long lastBuild = readFile('time.txt') as Long
    int finalNum = (now - lastBuild) / (1000*60*60)

    if( finalNum < 8 ) {
        currentBuild.result = 'SUCCESS'
        echo finalNum + " hours since the last build. Downstream job not run."
        return
    }

    stage ('downstream') {

        //run downstream job

    }
}

Basically this will

  1. Run a curl command on the Jenkins REST API to get the info on the last successful build and store it in a temp file

  2. Use jq to parse said info and extract the timestamp field, which is in Epoch time. This is stored to a file.

  3. The file is archived to the job and then read into a variable. This timestamp is compared to the current time, (gotten at the top of the job), and if the break between them is less than eight hours the job is "failed" out with a success and error message.

  4. If the time is over eight hours, the job continues on to build the downstream job.

1

This might work. I used an example X of two hours prior.

lastBuild = currentBuild.getPreviousBuild()

if Date(lastBuild.timestamp) < new Date().minusHours(2) {
  <do your thing here>
}

You may have to whitelist Date().

Cobbled together from this Cloudbees answer.

3
  • This sounds like it works based on the job currently running; I need it to check a downstream job's last build time (ie, a separate job) and respond based on that
    – Alex
    Commented Apr 26, 2017 at 12:40
  • 1
    Crud, I can't think of a clean way to do that. You might have to fall back on Jenkins' REST API and curl (synchronous things like HTTP requests are discouraged in the Groovy part of pipelines). Commented Apr 26, 2017 at 20:00
  • You might be able to use this in the downstream job though. Commented May 4, 2017 at 15:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.