Answers: <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>
  
Answers: CC BY-SA 3.0
Answers: 2017-05-01T13:08:20.840Z
Answers: 2017-05-01T13:13:25.533Z
Answers: 2017-05-01T13:13:25.533Z
Answers: Alex
Answers: <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>
  
Answers: CC BY-SA 3.0
Answers: 2017-05-04T15:57:41.183Z
Answers: 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!
Answers: Alex
Answers: CC BY-SA 3.0
Answers: 2017-05-04T16:00:12.677Z
Answers: 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.
Answers: lawnmowerlatte
Answers: CC BY-SA 3.0
Answers: 2017-05-04T15:54:54.033Z
Answers: 2017-05-04T15:54:54.033Z
Answers: lawnmowerlatte
Answers: <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>
  
Answers: CC BY-SA 3.0
Answers: 2017-04-26T12:40:16.243Z
Answers: 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
Answers: Alex
Answers: CC BY-SA 3.0
Answers: 2017-04-26T20:00:20.523Z
Answers: 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).
Answers: Steve Johnson
Answers: CC BY-SA 3.0
Answers: 2017-05-04T15:50:20.123Z
Answers: You might be able to use this in the downstream job though.
Answers: lawnmowerlatte
Answers: CC BY-SA 3.0
Answers: 2017-04-25T23:59:21.530Z
Answers: 2017-04-26T01:01:30.627Z
Answers: 2017-04-26T01:01:30.627Z
Answers: Steve Johnson
Body: <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>
  
Tags: <jenkins><jenkins-pipeline><groovy>
Title: Jenkins Pipeline downstream job; exit unless it hasn't run in the last x hours
UserDisplayName: Alex
ThreadText: # 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
  
  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](https://stedolan.github.io/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.
  
  
  ---
  
  ### 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 username_2'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) {
    <do your thing here>
  }
  
  ```
  
  You may have to whitelist `Date()`.
  
  Cobbled together from [this Cloudbees answer](https://support.cloudbees.com/hc/en-us/articles/217591038-How-to-Iterate-Through-the-Last-Successful-Builds-in-Pipeline-Job).
  
  > **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.  
  
  ---
  
  