Issue
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
- Name:
- Choice Parameter
- Name:
JOB
- Choices:
... the jobs' names you'd like to start with this ...
- Name:
- Node [NodeLabel Parameter Plugin]
Build
- Conditional step (single) [Conditional BuildStep Plugin]
- Run?:
Not
- !:
Execute Shell
- Command:
- !:
- Run?:
- Conditional step (single) [Conditional BuildStep Plugin]
#!/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
- Result:
- 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
- Name:
- Projects to build:
- Build Triggers:
- Run?:
Answered By - Gerold Broser
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)