Skip to content

Commit 9b5b364

Browse files
Updated Wait for Job and Add new Command for Approving Hold Jobs (#103)
* Updated wait_for_job to handle multiple jobs. Also created a command to approve on hold jobs by name
1 parent 75006ca commit 9b5b364

File tree

2 files changed

+154
-32
lines changed

2 files changed

+154
-32
lines changed

src/commands/approve_job.yml

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
description: |
2+
This command approves a hold job(s) by name.
3+
This requires a Circle CI token be set as $t
4+
5+
parameters:
6+
job-name:
7+
description: A list of comma separated hold jobs to approve
8+
type: string
9+
run-on-branch:
10+
description: |
11+
The branches to actually wait on. By default this waits on all branches. If set to anything but
12+
'*' the wait will run only on the specified branch
13+
type: string
14+
default: "*"
15+
kill-gracefully:
16+
description: If true it completes and lets future steps continue
17+
type: string
18+
default: "true"
19+
when:
20+
description: Allows the user to set when conditions
21+
type: enum
22+
enum: [
23+
"always",
24+
"on_success",
25+
"on_fail"
26+
]
27+
default: "on_success"
28+
circleci-api-key:
29+
default: CIRCLE_TOKEN
30+
description: >-
31+
In case you use a different Environment Variable Name than
32+
CIRCLE_TOKEN, supply it here.
33+
type: env_var_name
34+
35+
steps:
36+
- run:
37+
name: Swissknife - Approve On Hold Job(s) by Name
38+
when: << parameters.when >>
39+
command: |
40+
if [ -z "$BASH" ]; then
41+
echo Bash not installed.
42+
exit 1
43+
fi
44+
hash jq 2>/dev/null || { echo >&2 "jq is not installed. Aborting."; exit 1; }
45+
if [[ "$<< parameters.circleci-api-key >>" == "" ]]; then
46+
echo "<< parameters.circleci-api-key >> not set. Set a token to access the circle API in the env var << parameters.circleci-api-key >>";
47+
exit 1;
48+
fi
49+
50+
if [[ "<< parameters.run-on-branch >>" != "*" && "<< parameters.run-on-branch >>" != "$CIRCLE_BRANCH" ]]; then
51+
echo "Chosen to run only on << parameters.run-on-branch >> and currently we are on $CIRCLE_BRANCH, exiting";
52+
exit 0;
53+
fi
54+
55+
mkdir -p /tmp/swissknife
56+
57+
58+
get_job_id_and_type() {
59+
local NAME_OF_JOB="$1"
60+
local ID=""
61+
62+
curl --header "Circle-Token: $<< parameters.circleci-api-key >>" -f -s https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}/job > /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json
63+
ID=$(jq -r ".items[] | select(.name==\"${NAME_OF_JOB}\") | .id" /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
64+
TYPE=$(jq -r ".items[] | select(.name==\"${NAME_OF_JOB}\") | .type" /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
65+
echo "${ID} ${TYPE}"
66+
}
67+
68+
69+
job_list="<< parameters.job-name >>"
70+
71+
for job_name in ${job_list//,/ }
72+
do
73+
# Reset job id and job type
74+
job_id=""
75+
job_type=""
76+
77+
echo "Checking type of ${job_name}...."
78+
79+
read job_id job_type < <(get_job_id_and_type ${job_name})
80+
if [[ "$job_type" == "approval" ]]; then
81+
echo "${job_name} is an approval job!"
82+
echo "Moving onto approval...."
83+
status_code=$(curl --write-out %{http_code} --silent --output /dev/null --request POST "https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}/approve/${job_id}" --header "Circle-Token: ${<< parameters.circleci-api-key >>}")
84+
85+
if [[ "$status_code" -eq 202 ]] ; then
86+
echo "${job_name} has been approved!"
87+
else
88+
echo "Something went wrong! Status Code: ${status_code}"
89+
if [[ "<< parameters.kill-gracefully >>" == "true" ]]; then
90+
echo "Proceeding with future steps";
91+
break
92+
else
93+
echo "Failing job by exiting forcefully";
94+
exit 1;
95+
fi
96+
fi
97+
else
98+
echo "${job_name} is NOT approval job!"
99+
if [[ "<< parameters.kill-gracefully >>" == "true" ]]; then
100+
echo "Proceeding with future steps";
101+
break
102+
else
103+
echo "Failing job by exiting forcefully";
104+
exit 1;
105+
fi
106+
fi
107+
done

src/commands/wait_for_job.yml

+47-32
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
description: |
2-
This command waits for another job in this workflow. Since right now Circle CI doesnt let
2+
This command waits for a job(s) in this workflow. Since right now Circle CI doesn't let
33
you queue up jobs irrespective of whether they fail or not. This is a faux queue where
44
the command stalls till the other job succeeds.
55
This requires a Circle CI token be set as $CIRCLE_TOKEN
66
77
parameters:
88
job-name:
9-
description: The job on which to wait. If job not found continue immediately
9+
description: The job or jobs on which to wait. If job not found continue immediately. For multiple jobs the list must be comma separated.
1010
type: string
1111
max-wait-time:
1212
description: |
@@ -27,6 +27,12 @@ parameters:
2727
'*' the wait will run only on the specified branch
2828
type: string
2929
default: "*"
30+
circleci-api-key:
31+
default: CIRCLE_TOKEN
32+
description: >-
33+
In case you use a different Environment Variable Name than
34+
CIRCLE_TOKEN, supply it here.
35+
type: env_var_name
3036

3137
steps:
3238
- run:
@@ -37,8 +43,8 @@ steps:
3743
exit 1
3844
fi
3945
hash jq 2>/dev/null || { echo >&2 "jq is not installed. Aborting."; exit 1; }
40-
if [[ "$CIRCLE_TOKEN" == "" ]]; then
41-
echo "CIRCLE_TOKEN not set. Set a token to access the circle API in the env var CIRCLE_TOKEN";
46+
if [[ "$<< parameters.circleci-api-key >>" == "" ]]; then
47+
echo "<< parameters.circleci-api-key >> not set. Set a token to access the circle API in the env var << parameters.circleci-api-key >>";
4248
exit 1;
4349
fi
4450
@@ -47,42 +53,51 @@ steps:
4753
exit 0;
4854
fi
4955
50-
api_endpoint="api/v2/workflow/${CIRCLE_WORKFLOW_ID}/job"
51-
5256
mkdir -p /tmp/swissknife
5357
54-
# This is a global variable used to get return value for get_job_status
55-
job_status=""
56-
job_number=""
5758
5859
get_job_status() {
59-
wf_url="https://circleci.com/$api_endpoint?circle-token=${CIRCLE_TOKEN}"
60-
curl -f -s $wf_url > /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json
61-
job_status=$(jq -r '.items[] | select(.name=="<< parameters.job-name >>") | .status' /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
62-
job_number=$(jq -r '.items[] | select(.name=="<< parameters.job-name >>") | .job_number' /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
60+
local NAME_OF_JOB="$1"
61+
local STATUS=""
62+
local NUMBER=""
63+
64+
curl --header "Circle-Token: $<< parameters.circleci-api-key >>" -f -s https://circleci.com/api/v2/workflow/${CIRCLE_WORKFLOW_ID}/job > /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json
65+
STATUS=$(jq -r ".items[] | select(.name==\"${NAME_OF_JOB}\") | .status" /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
66+
NUMBER=$(jq -r ".items[] | select(.name==\"${NAME_OF_JOB}\") | .job_number" /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
67+
echo "${STATUS} ${NUMBER}"
6368
}
6469
65-
current_wait_time=0
6670
67-
while true; do
68-
get_job_status
69-
if [[ "$job_status" == "success" || "$job_status" == "failed" || "$job_status" == "canceled" || "$job_status" == "" ]]; then
70-
echo "Its finally my turn. exiting"
71-
exit 0
72-
else
73-
echo "Looks like the other guy ($job_number) is still not done ($job_status)."
74-
echo "Going to sleep for << parameters.sleep-time-between-checks >>"
75-
sleep << parameters.sleep-time-between-checks >>
76-
current_wait_time=$(( current_wait_time + << parameters.sleep-time-between-checks >> ))
77-
fi
71+
job_list="<< parameters.job-name >>"
72+
73+
for job_name in ${job_list//,/ }
74+
do
75+
# Reset job status, job number and wait time
76+
job_status=""
77+
job_number=""
78+
current_wait_time=0
7879
79-
if (( $current_wait_time > << parameters.max-wait-time >> )); then
80-
if [[ "<< parameters.kill-gracefully >>" == "true" ]]; then
81-
echo "Proceeding with future steps";
82-
exit 0;
80+
echo "Starting to check status of ${job_name}"
81+
while true; do
82+
read job_status job_number < <(get_job_status ${job_name})
83+
if [[ "$job_status" == "success" || "$job_status" == "failed" || "$job_status" == "canceled" || "$job_status" == "" ]]; then
84+
echo "Job, ${job_name}, has completed!"
85+
break
8386
else
84-
echo "Failing job by exiting forcefully";
85-
exit 1;
87+
echo "Looks like the other guy ($job_number) is still not done ($job_status)."
88+
echo "Going to sleep for << parameters.sleep-time-between-checks >>"
89+
sleep << parameters.sleep-time-between-checks >>
90+
current_wait_time=$(( current_wait_time + << parameters.sleep-time-between-checks >> ))
91+
fi
92+
93+
if (( $current_wait_time > << parameters.max-wait-time >> )); then
94+
if [[ "<< parameters.kill-gracefully >>" == "true" ]]; then
95+
echo "Proceeding with future steps";
96+
break
97+
else
98+
echo "Failing job by exiting forcefully";
99+
exit 1;
100+
fi
86101
fi
87-
fi
102+
done
88103
done

0 commit comments

Comments
 (0)