Search code examples
jenkinsjenkins-plugins

Jenkins - Stop concurrent job with same parameter


I have a Jenkins job for a db rollback script that uses a choice parameter for each environment (using NodeLabel Parameter Plugin).

I want the jobs to able to be run concurrently, but only for different environments.

"Execute concurrent builds if necessary" is enabled.

E.g. If the job is running for LIVE, allow someone to run the job again for TEST (this works). However, if LIVE is already running and someone runs the job for LIVE again, then do not run.

This plugin seems to suit my needs but is not shown on the list of available plugins in Manage Jenkins.

https://wiki.jenkins-ci.org/display/JENKINS/Concurrent+Run+Blocker+Plugin

Are there any other ways around this?


Solution

  • There's a solution with existing Jenkins plugins:

    • Create a Freestyle project named like Starter for concurrent builds exclusively on nodes.
    • ☑ This build is parameterized

      • Node   [NodeLabel Parameter Plugin]
        • Name: NODE
      • Choice Parameter
        • Name: JOB
        • Choices: ... the jobs' names you'd like to start with this ...
    • Build

     

    #!/bin/bash +x -e  
    # Bash 4 needed for associative arrays
    
    # From http://stackoverflow.com/questions/37678188/jenkins-stop-concurrent-job-with-same-parameter
    
    echo '  Build --> Conditional step (single) --> Execute Shell'
    echo "  Checking whether job '$JOB' runs on node '$NODE'"
    
    echo '  Creating array'
    declare -A computers
    
    # ------------------------------------------------------------------------
    # Declare your nodes and their executors here as mentioned, for instance,
    # in the API URI 'http://<jenkins>/computer/(master)/executors/0/api/xml':
    computers=(       #                          ^^^^^^            ^
      [master]="0 1 2 3"
      [slave]="0 1"
      )
    # Note: Executor indices DO NOT conform to the numbers in Jenkins' 
    #       Build Executor Status UI.
    # ------------------------------------------------------------------------
    
    echo "  Checking executors of node '$NODE'"
    for computer in ${!computers[@]} ; do
      for executorIdx in ${computers[$computer]} ; do
    
        if [[ $computer == $NODE ]] ; then
    
          if [[ "$computer" == "master" ]] ; then
            node="(${computer})"
          else
            node=$computer
          fi
          url="${JENKINS_URL}/computer/${node}/executors/${executorIdx}/api/xml?tree=currentExecutable\[url\]"
          echo "    $url"
    
          xml=$(curl -s $url)
          #echo $computer, $executorIdx, $xml
    
          if [[ "$xml" == *"/job/${JOB}"* ]] ; then
            echo "    Job '$JOB' is already building on '$computer' executor index '$executorIdx'"
            echo '  Exiting with 1'
            exit 1
          fi
        fi
      done
    done
    
    echo '  Exiting with 0'
    

     

    • Builder: Set the build result
      • Result: Aborted

     

    • Conditional step (single)
      • Run?: Current build status
      • Builder: Trigger/call build on other projects
        • Build Triggers:
          • Projects to build: $JOB   [ignore the error message]
          • Node Label parameter
            • Name: NODE   [or how you call it in your downstream job(s)]
            • Node: $NODE