@@ -6,5 +6,147 @@ debug() {
66 fi
77}
88
9- debug " this is a test"
10- echo " this is a test"
9+ tmp=" /tmp"
10+ pipeline_file=" ${tmp} /pipeline_status.json"
11+ workflows_file=" ${tmp} /workflow_status.json"
12+
13+ load_variables (){
14+ # just confirm our required variables are present
15+ : ${CIRCLE_BUILD_NUM:? " Required Env Variable not found!" }
16+ : ${CIRCLE_WORKFLOW_ID:? " Required Env Variable not found!" }
17+ : ${CIRCLE_PROJECT_USERNAME:? " Required Env Variable not found!" }
18+ : ${CIRCLE_PROJECT_REPONAME:? " Required Env Variable not found!" }
19+ : ${CIRCLE_REPOSITORY_URL:? " Required Env Variable not found!" }
20+ : ${CIRCLE_JOB:? " Required Env Variable not found!" }
21+ # Only needed for private projects
22+ if [ -z " ${CIRCLECI_USER_AUTH} " ]; then
23+ echo " CIRCLECI_USER_AUTH not set. Private projects will be inaccessible."
24+ else
25+ fetch " https://circleci.com/api/v2/me" " /tmp/me.cci"
26+ me=$( jq -e ' .id' /tmp/me.cci)
27+ echo " Using API key for user: ${me} "
28+ fi
29+ }
30+
31+ fetch (){
32+ debug " Making API Call to ${1} "
33+ url=$1
34+ target=$2
35+ debug " API CALL ${url} "
36+ http_response=$( curl -s -X GET -H " Authorization: Basic ${CIRCLECI_USER_AUTH} " -H " Content-Type: application/json" -o " ${target} " -w " %{http_code}" " ${url} " )
37+ if [ $http_response != " 200" ]; then
38+ echo " ERROR: Server returned error code: $http_response "
39+ cat ${target}
40+ # exit 1
41+ else
42+ debug " API Success"
43+ fi
44+ }
45+
46+ fetch_pipelines (){
47+ : ${CIRCLE_BRANCH:? " Required Env Variable not found!" }
48+ echo " Only blocking execution if running previous workflows on branch: ${CIRCLE_BRANCH} "
49+ pipelines_api_url_template=" https://circleci.com/api/v2/project/gh/${CIRCLE_PROJECT_USERNAME} /${CIRCLE_PROJECT_REPONAME} /pipeline?branch=${CIRCLE_BRANCH} "
50+
51+ debug " DEBUG Attempting to access CircleCI API. If the build process fails after this step, ensure your CIRCLECI_USER_AUTH is set."
52+ fetch " $pipelines_api_url_template " " ${pipeline_file} "
53+ echo " DEBUG API access successful"
54+ }
55+
56+ fetch_pipeline_workflows (){
57+ for pipeline in ` jq -r " .items[] | .id //empty" ${pipeline_file} | uniq`
58+ do
59+ debug " Checking time of pipeline: ${pipeline} "
60+ pipeline_detail=${tmp} /pipeline-${pipeline} .json
61+ fetch " https://circleci.com/api/v2/pipeline/${pipeline} /workflow" " ${pipeline_detail} "
62+ created_at=` jq -r ' .items[] | .created_at' ${pipeline_detail} `
63+ debug " Pipeline was created at: ${created_at} "
64+ done
65+ jq -s ' [.[].items[]]' ${tmp} /pipeline-* .json > ${workflows_file}
66+ }
67+
68+ load_current_workflow_values (){
69+ my_commit_time=` jq ' .[] | select (.pipeline_number == ${CIRCLE_BUILD_NUM}).created_at' ${workflows_file} `
70+ my_workflow_id` jq ' .[] | select (.pipeline_number == ${CIRCLE_BUILD_NUM}).id' ${workflows_file} `
71+ }
72+
73+ update_comparables (){
74+ fetch_pipelines
75+
76+ fetch_pipeline_workflows
77+
78+ load_current_workflow_values
79+
80+ echo " This job will block until no previous workflows have *any* workflows running."
81+ oldest_running_workflow_id=` jq ' . | sort_by(.created_at) | .[0].id' ${workflows_file} `
82+ oldest_commit_time=` jq ' . | sort_by(.created_at) | .[0].created_at' ${workflows_file} `
83+ if [ -z " ${oldest_commit_time} " || -z " ${oldest_running_workflow_id} " ]; then
84+ echo " ERROR: API Error - unable to load previous workflow timings. File a bug"
85+ exit 1
86+ fi
87+
88+ debug " Oldest workflow: ${oldest_running_workflow_id} "
89+ }
90+
91+ cancel_current_workflow (){
92+ echo " Cancelleing workflow ${my_workflow_id} "
93+ cancel_api_url_template=" https://circleci.com/api/v2/workflow/${my_workflow_id} "
94+ curl -s -X POST -H " Authorization: Basic ${CIRCLECI_USER_AUTH} " -H " Content-Type: application/json" $cancel_api_url_template > /dev/null
95+ }
96+
97+ if [ " ${CONFIG_ONLY_ON_BRANCH} " = " *" ] || [ " ${CONFIG_ONLY_ON_BRANCH} " = " ${CIRCLE_BRANCH} " ]; then
98+ echo " ${CIRCLE_BRANCH} queueable"
99+ else
100+ echo " Queueing only happens on ${CONFIG_ONLY_ON_BRANCH} branch, skipping queue"
101+ exit 0
102+ fi
103+
104+ # ## Set values that wont change while we wait
105+ load_variables
106+ max_time=${CONFIG_TIME}
107+ echo " This build will block until all previous builds complete."
108+ echo " Max Queue Time: ${max_time} minutes."
109+ wait_time=0
110+ loop_time=11
111+ max_time_seconds=$(( max_time * 60 ))
112+
113+ # ## Queue Loop
114+ confidence=0
115+ while true ; do
116+ update_comparables
117+ echo " This Workflow Timestamp: $my_commit_time "
118+ echo " Oldest Workflow Timestamp: $oldest_commit_time "
119+ if [[ ! -z " $my_commit_time " ]] && [[ " $oldest_commit_time " > " $my_commit_time " || " $oldest_commit_time " = " $my_commit_time " ]] ; then
120+ # API returns Y-M-D HH:MM (with 24 hour clock) so alphabetical string compare is accurate to timestamp compare as well
121+ # Workflow API does not include pending, so it is posisble we queried in between a workfow transition, and we;re NOT really front of line.
122+ if [ $confidence -lt ${CONFIG_CONFIDENCE} ]; then
123+ # To grow confidence, we check again with a delay.
124+ confidence=$(( confidence+ 1 ))
125+ echo " API shows no previous workflows, but it is possible a previous workflow has pending jobs not yet visible in API."
126+ echo " Rerunning check ${confidence} /${CONFIG_CONFIDENCE} "
127+ else
128+ echo " Front of the line, WooHoo!, Build continuing"
129+ break
130+ fi
131+ else
132+ # If we fail, reset confidence
133+ confidence=0
134+ echo " This build (${CIRCLE_BUILD_NUM} ) is queued, waiting for workflow (${oldest_running_workflow_id} ) to complete."
135+ echo " Total Queue time: ${wait_time} seconds."
136+ fi
137+
138+ if [ $wait_time -ge $max_time_seconds ]; then
139+ echo " Max wait time exceeded, considering response."
140+ if [ " ${CONFIG_DONT_QUIT} " == " 1" ]; then
141+ echo " Orb parameter dont-quit is set to true, letting this job proceed!"
142+ exit 0
143+ else
144+ cancel_current_workflow
145+ sleep 10 # wait for API to cancel this job, rather than showing as failure
146+ exit 1 # but just in case, fail job
147+ fi
148+ fi
149+
150+ sleep $loop_time
151+ wait_time=$(( loop_time + wait_time ))
152+ done
0 commit comments