update ci-restart script with code that works and is testable locally

This commit is contained in:
krande
2023-03-12 11:19:10 +01:00
committed by Thomas Krijnen
parent 8820a1dcc3
commit 03ff34f89f
2 changed files with 96 additions and 43 deletions
+82 -36
View File
@@ -1,57 +1,103 @@
import pathlib
import shutil
import requests import requests
import zipfile
import os
# To test this locally, set these environment variables
REPO_OWNER = os.environ.get("REPO_OWNER", "IfcOpenShell/IfcOpenShell")
MY_WORKFLOW = os.environ.get("MY_WORKFLOW", "ci-ifcopenshell-conda-daily")
WORKFLOW_RUN_ID = os.environ.get("WORKFLOW_RUN_ID", None)
TOKEN = os.environ.get("GITHUB_TOKEN", None)
# Create a fine-grained personal access token for the repo in question with repo permissions "actions:read"
# See https://github.com/settings/tokens?type=beta
# This is a list of strings that indicate that a job has stopped abruptly.
SIGNS_OF_STOPPAGE = [
"Error: The operation was canceled.",
"fatal error C1060: compiler is out of heap space",
]
def get_ci_jobs(repo_name): def start_request_session():
url = f"https://api.github.com/repos/{repo_name}/actions/runs" s = requests.Session()
response = requests.get(url) headers = {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
}
if TOKEN:
headers["Authorization"] = f"Bearer {TOKEN}"
s.headers = headers
return s
def get_ci_run(repo_name, run_id):
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{run_id}"
s = start_request_session()
response = s.get(url)
return response.json() return response.json()
def evaluate_log_file_for_abrupt_stop(log_file):
with open(log_file) as f:
for i, line in enumerate(f):
for sign in SIGNS_OF_STOPPAGE:
if sign in line:
print(f"Found sign of abrupt stoppage in [line {i}]: '{sign}'")
return True
return False
def get_ci_specific_run_specific_failure_details(repo_name, run_id): def get_ci_specific_run_specific_failure_details(repo_name, run_id):
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{run_id}/attempts/1/logs" url = f"https://api.github.com/repos/{repo_name}/actions/runs/{run_id}/attempts/1/logs"
response = requests.get(url) s = start_request_session()
return response.json() response = s.get(url)
# SAVE zip file
with open("logs.zip", "wb") as f:
f.write(response.content)
# unzip file
with zipfile.ZipFile("logs.zip", "r") as zip_ref:
zip_ref.extractall("logs")
failed_logs = []
for file in pathlib.Path("logs").iterdir():
if file.is_dir():
continue
if evaluate_log_file_for_abrupt_stop(file):
failed_logs.append(file)
return failed_logs
def restart_job(repo_name, job_id): def restart_job(repo_name, job_id):
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{job_id}/rerun" url = f"https://api.github.com/repos/{repo_name}/actions/runs/{job_id}/rerun-failed-jobs"
response = requests.post(url) s = start_request_session()
response = s.post(url)
return response.json() return response.json()
def logs_contain_signs_of_stoppage_due_to_lack_of_vm_resources(logs):
"""Do something like this?"""
for log in logs["lines"]:
if log["name"] == "stderr":
if "Error: The operation was canceled." in log["text"]:
return True
if "fatal error C1060: compiler is out of heap space" in log["text"]:
return True
return False
def eval_jobs(): def eval_jobs():
jobs = get_ci_jobs("IfcOpenShell/IfcOpenShell") run = get_ci_run(REPO_OWNER, WORKFLOW_RUN_ID)
for job in jobs["workflow_runs"]: if run["run_attempt"] > 1:
if job["name"] != "ci-ifcopenshell-conda-daily": print("This is not the first attempt. Exiting")
continue return
failed_logs = get_ci_specific_run_specific_failure_details(REPO_OWNER, WORKFLOW_RUN_ID)
if job["status"] != "completed": if len(failed_logs) == 0:
continue print("No runs exhibit signs of abrupt stoppage")
if job["conclusion"] != "failure": return
continue
if job["run_attempt"] > 1: print("restarting job", WORKFLOW_RUN_ID)
continue r = restart_job(REPO_OWNER, WORKFLOW_RUN_ID)
print(r)
logs = get_ci_specific_run_specific_failure_details("IfcOpenShell/IfcOpenShell", job["id"]) shutil.rmtree("logs")
os.remove("logs.zip")
print(logs)
print("restarting job", job["id"])
if logs_contain_signs_of_stoppage_due_to_lack_of_vm_resources(logs):
r = restart_job("IfcOpenShell/IfcOpenShell", job["id"])
print(r)
if __name__ == "__main__": if __name__ == "__main__":
@@ -5,12 +5,9 @@ on:
workflows: [ ci-ifcopenshell-conda-daily ] workflows: [ ci-ifcopenshell-conda-daily ]
types: types:
- completed - completed
push: # Remove this before merging
branches:
- add-conda-daily-restart-workflow
env: env:
REPO_OWNER: IfcOpenShell REPO_OWNER: IfcOpenShell/IfcOpenShell
MY_WORKFLOW: ci-ifcopenshell-conda-daily MY_WORKFLOW: ci-ifcopenshell-conda-daily
jobs: jobs:
@@ -18,10 +15,20 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }} if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps: steps:
- uses: actions/setup-python@v2 - name: checkout
uses: actions/checkout@v3
- name: Use python 3.11
uses: actions/setup-python@v2
with: with:
python-version: '3.10' python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Check for failed runs - name: Check for failed runs
id: check-failed-runs env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
run: | run: |
python check_repo_ci_jobs.py python check_repo_ci_jobs.py
working-directory: .github/workflows