Skip to content

Commit c0f7d5f

Browse files
committed
Force cancel stuck workflow runs
1 parent 22a94ea commit c0f7d5f

1 file changed

Lines changed: 29 additions & 1 deletion

File tree

.github/scripts/ci_common.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,13 +270,41 @@ def cancel_older_workflow_runs(repo, token, workflow_name, branch, current_run_i
270270
continue
271271
if current_created and run.get("created_at", "") >= current_created:
272272
continue
273-
json_request("POST", f"https://api.github.com/repos/{repo}/actions/runs/{run['id']}/cancel", headers)
273+
cancel_workflow_run(repo, headers, run["id"])
274274
cancelled.append(run["id"])
275275
print(f"Cancelled superseded {workflow_name} run {run['id']} on {branch}.")
276276
if not cancelled:
277277
print(f"No superseded {workflow_name} runs found on {branch}.")
278278

279279

280+
def workflow_run_status(repo, headers, run_id):
281+
run = json_request("GET", f"https://api.github.com/repos/{repo}/actions/runs/{run_id}", headers)
282+
return run.get("status"), run.get("conclusion")
283+
284+
285+
def wait_workflow_run_completed(repo, headers, run_id, timeout_seconds):
286+
deadline = time.monotonic() + timeout_seconds
287+
while time.monotonic() < deadline:
288+
status, conclusion = workflow_run_status(repo, headers, run_id)
289+
if status == "completed":
290+
return conclusion or ""
291+
time.sleep(5)
292+
status, _ = workflow_run_status(repo, headers, run_id)
293+
return "" if status != "completed" else "completed"
294+
295+
296+
def cancel_workflow_run(repo, headers, run_id):
297+
json_request("POST", f"https://api.github.com/repos/{repo}/actions/runs/{run_id}/cancel", headers)
298+
conclusion = wait_workflow_run_completed(repo, headers, run_id, 45)
299+
if conclusion:
300+
return
301+
print(f"Workflow run {run_id} did not stop after cancel; force-cancelling.")
302+
json_request("POST", f"https://api.github.com/repos/{repo}/actions/runs/{run_id}/force-cancel", headers)
303+
conclusion = wait_workflow_run_completed(repo, headers, run_id, 60)
304+
if not conclusion:
305+
raise CiError(f"Workflow run {run_id} is still running after force-cancel.")
306+
307+
280308
def parameter(actions, name):
281309
for action in actions or []:
282310
for parameter in action.get("parameters") or []:

0 commit comments

Comments
 (0)