<p>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;</p>

<pre><code>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" &gt; $lastBuild

        jq -j '.timestamp' &lt; $lastBuild &gt; time.txt'''

    }

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

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

    stage ('downstream') {

        //run downstream job

    }
}
</code></pre>

<p>Basically this will </p>

<ol>
<li><p>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</p></li>
<li><p>Use <a href="https://stedolan.github.io/jq/" rel="nofollow noreferrer">jq</a> to parse said info and extract the timestamp field, which is in Epoch time. This is stored to a file.</p></li>
<li><p>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.</p></li>
<li><p>If the time is over eight hours, the job continues on to build the downstream job.</p></li>
</ol>

CC BY-SA 3.0
2017-05-01T13:08:20.840Z
2017-05-01T13:13:25.533Z
2017-05-01T13:13:25.533Z
Alex
<p>To synthesize Alex and Steve Johnson's answers, you could put this at the top of your downstream job:</p>

<pre><code>lastBuild = currentBuild.getPreviousBuild()
delay = 2

if Date(lastBuild.timestamp) &gt;= new Date().minusHours(delay) {
    currentBuild.result = 'SUCCESS'
    echo "Less than ${delay} hours since the last build. Job will not run."
    return
}
</code></pre>

CC BY-SA 3.0
2017-05-04T15:57:41.183Z
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
CC BY-SA 3.0
2017-05-04T16:00:12.677Z
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.
lawnmowerlatte
CC BY-SA 3.0
2017-05-04T15:54:54.033Z
2017-05-04T15:54:54.033Z
lawnmowerlatte
<p>This might work.  I used an example X of two hours prior.</p>

<pre><code>lastBuild = currentBuild.getPreviousBuild()

if Date(lastBuild.timestamp) &lt; new Date().minusHours(2) {
  &lt;do your thing here&gt;
}
</code></pre>

<p>You may have to whitelist <code>Date()</code>.</p>

<p>Cobbled together from <a href="https://support.cloudbees.com/hc/en-us/articles/217591038-How-to-Iterate-Through-the-Last-Successful-Builds-in-Pipeline-Job" rel="nofollow noreferrer">this Cloudbees answer</a>.</p>

CC BY-SA 3.0
2017-04-26T12:40:16.243Z
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
CC BY-SA 3.0
2017-04-26T20:00:20.523Z
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).
Steve Johnson
CC BY-SA 3.0
2017-05-04T15:50:20.123Z
You might be able to use this in the downstream job though.
lawnmowerlatte
CC BY-SA 3.0
2017-04-25T23:59:21.530Z
2017-04-26T01:01:30.627Z
2017-04-26T01:01:30.627Z
Steve Johnson
<p>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?</p>

<p>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. </p>

<p>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.</p>

<p>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. </p>

<jenkins><jenkins-pipeline><groovy>
Jenkins Pipeline downstream job; exit unless it hasn't run in the last x hours
Alex
# Jenkins Pipeline downstream job; exit unless it hasn't run in the last x hours

(Asked by: username_0 on 2017-04-25)

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.

**Tags:** jenkins, jenkins-pipeline, groovy


---

## 3 answers

### Answer by username_0 on 2017-05-01. Score: 2 | Accepted answer

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 

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
Use jq to parse said info and extract the timestamp field, which is in Epoch time. This is stored to a file.
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.
If the time is over eight hours, the job continues on to build the downstream job.


---

### Answer by username_1 on 2017-05-04. Score: 4

To synthesize username_0 and username_2'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
}

> **Comments:**
> **username_0**: 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!  
> **username_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.  

---

### Answer by username_2 on 2017-04-25. Score: 1

This might work.  I used an example X of two hours prior.
lastBuild = currentBuild.getPreviousBuild()

if Date(lastBuild.timestamp) < new Date().minusHours(2) {
  
}

You may have to whitelist Date().
Cobbled together from this Cloudbees answer.

> **Comments:**
> **username_0**: 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  
> **username_2**: 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).  
> **username_1**: You might be able to use this in the downstream job though.  

---

