Skip to content

Commit

Permalink
Updated Wait for Job and Add new Command for Approving Hold Jobs (#103)
Browse files Browse the repository at this point in the history
* Updated wait_for_job to handle multiple jobs. Also created a command to approve on hold jobs by name
  • Loading branch information
james-crowley authored Jun 24, 2022
1 parent 75006ca commit 9b5b364
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 32 deletions.
107 changes: 107 additions & 0 deletions src/commands/approve_job.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
description: |
This command approves a hold job(s) by name.
This requires a Circle CI token be set as $t
parameters:
job-name:
description: A list of comma separated hold jobs to approve
type: string
run-on-branch:
description: |
The branches to actually wait on. By default this waits on all branches. If set to anything but
'*' the wait will run only on the specified branch
type: string
default: "*"
kill-gracefully:
description: If true it completes and lets future steps continue
type: string
default: "true"
when:
description: Allows the user to set when conditions
type: enum
enum: [
"always",
"on_success",
"on_fail"
]
default: "on_success"
circleci-api-key:
default: CIRCLE_TOKEN
description: >-
In case you use a different Environment Variable Name than
CIRCLE_TOKEN, supply it here.
type: env_var_name

steps:
- run:
name: Swissknife - Approve On Hold Job(s) by Name
when: << parameters.when >>
command: |
if [ -z "$BASH" ]; then
echo Bash not installed.
exit 1
fi
hash jq 2>/dev/null || { echo >&2 "jq is not installed. Aborting."; exit 1; }
if [[ "$<< parameters.circleci-api-key >>" == "" ]]; then
echo "<< parameters.circleci-api-key >> not set. Set a token to access the circle API in the env var << parameters.circleci-api-key >>";
exit 1;
fi
if [[ "<< parameters.run-on-branch >>" != "*" && "<< parameters.run-on-branch >>" != "$CIRCLE_BRANCH" ]]; then
echo "Chosen to run only on << parameters.run-on-branch >> and currently we are on $CIRCLE_BRANCH, exiting";
exit 0;
fi
mkdir -p /tmp/swissknife
get_job_id_and_type() {
local NAME_OF_JOB="$1"
local ID=""
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
ID=$(jq -r ".items[] | select(.name==\"${NAME_OF_JOB}\") | .id" /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
TYPE=$(jq -r ".items[] | select(.name==\"${NAME_OF_JOB}\") | .type" /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
echo "${ID} ${TYPE}"
}
job_list="<< parameters.job-name >>"
for job_name in ${job_list//,/ }
do
# Reset job id and job type
job_id=""
job_type=""
echo "Checking type of ${job_name}...."
read job_id job_type < <(get_job_id_and_type ${job_name})
if [[ "$job_type" == "approval" ]]; then
echo "${job_name} is an approval job!"
echo "Moving onto approval...."
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 >>}")
if [[ "$status_code" -eq 202 ]] ; then
echo "${job_name} has been approved!"
else
echo "Something went wrong! Status Code: ${status_code}"
if [[ "<< parameters.kill-gracefully >>" == "true" ]]; then
echo "Proceeding with future steps";
break
else
echo "Failing job by exiting forcefully";
exit 1;
fi
fi
else
echo "${job_name} is NOT approval job!"
if [[ "<< parameters.kill-gracefully >>" == "true" ]]; then
echo "Proceeding with future steps";
break
else
echo "Failing job by exiting forcefully";
exit 1;
fi
fi
done
79 changes: 47 additions & 32 deletions src/commands/wait_for_job.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
description: |
This command waits for another job in this workflow. Since right now Circle CI doesnt let
This command waits for a job(s) in this workflow. Since right now Circle CI doesn't let
you queue up jobs irrespective of whether they fail or not. This is a faux queue where
the command stalls till the other job succeeds.
This requires a Circle CI token be set as $CIRCLE_TOKEN
parameters:
job-name:
description: The job on which to wait. If job not found continue immediately
description: The job or jobs on which to wait. If job not found continue immediately. For multiple jobs the list must be comma separated.
type: string
max-wait-time:
description: |
Expand All @@ -27,6 +27,12 @@ parameters:
'*' the wait will run only on the specified branch
type: string
default: "*"
circleci-api-key:
default: CIRCLE_TOKEN
description: >-
In case you use a different Environment Variable Name than
CIRCLE_TOKEN, supply it here.
type: env_var_name

steps:
- run:
Expand All @@ -37,8 +43,8 @@ steps:
exit 1
fi
hash jq 2>/dev/null || { echo >&2 "jq is not installed. Aborting."; exit 1; }
if [[ "$CIRCLE_TOKEN" == "" ]]; then
echo "CIRCLE_TOKEN not set. Set a token to access the circle API in the env var CIRCLE_TOKEN";
if [[ "$<< parameters.circleci-api-key >>" == "" ]]; then
echo "<< parameters.circleci-api-key >> not set. Set a token to access the circle API in the env var << parameters.circleci-api-key >>";
exit 1;
fi
Expand All @@ -47,42 +53,51 @@ steps:
exit 0;
fi
api_endpoint="api/v2/workflow/${CIRCLE_WORKFLOW_ID}/job"
mkdir -p /tmp/swissknife
# This is a global variable used to get return value for get_job_status
job_status=""
job_number=""
get_job_status() {
wf_url="https://circleci.com/$api_endpoint?circle-token=${CIRCLE_TOKEN}"
curl -f -s $wf_url > /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json
job_status=$(jq -r '.items[] | select(.name=="<< parameters.job-name >>") | .status' /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
job_number=$(jq -r '.items[] | select(.name=="<< parameters.job-name >>") | .job_number' /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
local NAME_OF_JOB="$1"
local STATUS=""
local NUMBER=""
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
STATUS=$(jq -r ".items[] | select(.name==\"${NAME_OF_JOB}\") | .status" /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
NUMBER=$(jq -r ".items[] | select(.name==\"${NAME_OF_JOB}\") | .job_number" /tmp/swissknife/wf_$CIRCLE_WORKFLOW_ID.json)
echo "${STATUS} ${NUMBER}"
}
current_wait_time=0
while true; do
get_job_status
if [[ "$job_status" == "success" || "$job_status" == "failed" || "$job_status" == "canceled" || "$job_status" == "" ]]; then
echo "Its finally my turn. exiting"
exit 0
else
echo "Looks like the other guy ($job_number) is still not done ($job_status)."
echo "Going to sleep for << parameters.sleep-time-between-checks >>"
sleep << parameters.sleep-time-between-checks >>
current_wait_time=$(( current_wait_time + << parameters.sleep-time-between-checks >> ))
fi
job_list="<< parameters.job-name >>"
for job_name in ${job_list//,/ }
do
# Reset job status, job number and wait time
job_status=""
job_number=""
current_wait_time=0
if (( $current_wait_time > << parameters.max-wait-time >> )); then
if [[ "<< parameters.kill-gracefully >>" == "true" ]]; then
echo "Proceeding with future steps";
exit 0;
echo "Starting to check status of ${job_name}"
while true; do
read job_status job_number < <(get_job_status ${job_name})
if [[ "$job_status" == "success" || "$job_status" == "failed" || "$job_status" == "canceled" || "$job_status" == "" ]]; then
echo "Job, ${job_name}, has completed!"
break
else
echo "Failing job by exiting forcefully";
exit 1;
echo "Looks like the other guy ($job_number) is still not done ($job_status)."
echo "Going to sleep for << parameters.sleep-time-between-checks >>"
sleep << parameters.sleep-time-between-checks >>
current_wait_time=$(( current_wait_time + << parameters.sleep-time-between-checks >> ))
fi
if (( $current_wait_time > << parameters.max-wait-time >> )); then
if [[ "<< parameters.kill-gracefully >>" == "true" ]]; then
echo "Proceeding with future steps";
break
else
echo "Failing job by exiting forcefully";
exit 1;
fi
fi
fi
done
done

0 comments on commit 9b5b364

Please sign in to comment.