You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/tools/ui_reports_generator/github.py

115 lines
3.7 KiB

from __future__ import annotations
import json
import os
from datetime import datetime
from pathlib import Path
from typing import Iterator
import requests
from common_all import AnyDict, BranchInfo
HERE = Path(__file__).parent
GITHUB_PR_API = "https://api.github.com/repos/trezor/trezor-firmware/pulls"
GH_TOKEN = os.getenv("GH_TOKEN")
GH_HEADERS = {"Authorization": f"token {GH_TOKEN}"} if GH_TOKEN else {}
def load_cache_file() -> AnyDict:
return json.loads(CACHE_FILE.read_text())
def load_branches_cache() -> dict[str, BranchInfo]:
cache_dict = load_cache_file()["branches"]
return {key: BranchInfo.from_dict(value) for key, value in cache_dict.items()}
def load_metadata_cache() -> AnyDict:
return load_cache_file()["metadata"]
def update_cache(cache_dict: dict[str, BranchInfo]) -> None:
CACHE.update(cache_dict)
json_writable_cache_dict = {key: value.to_dict() for key, value in CACHE.items()}
content = {
"branches": json_writable_cache_dict,
"metadata": {
"last_update_timestamp": int(datetime.now().timestamp()),
"last_update": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
},
}
CACHE_FILE.write_text(json.dumps(content, indent=2))
CACHE_FILE = HERE / "github_cache.json"
if not CACHE_FILE.exists():
CACHE_FILE.write_text("{}")
CACHE: dict[str, BranchInfo] = load_branches_cache()
def get_commit_ts(commit_hash: str) -> int:
res = requests.get(
f"https://api.github.com/repos/trezor/trezor-firmware/commits/{commit_hash}",
headers=GH_HEADERS,
)
res.raise_for_status()
return int(
datetime.fromisoformat(
res.json()["commit"]["committer"]["date"].replace("Z", "")
).timestamp()
)
def get_all_gh_pulls() -> list[AnyDict]:
res = requests.get(GITHUB_PR_API, headers=GH_HEADERS)
res.raise_for_status()
return res.json()
def yield_recently_updated_gh_pr_branches() -> Iterator[BranchInfo]:
for pr in get_all_gh_pulls():
last_commit_sha = pr["head"]["sha"]
branch_name = pr["head"]["ref"]
print(f"Getting branch {branch_name}")
# Skip when we already have this commit in cache (and pipeline is finished)
if branch_name in CACHE:
cache_info = CACHE[branch_name]
if cache_info.last_commit_sha == last_commit_sha:
still_running = False
for job_info in cache_info.job_infos.values():
if job_info.status == "Running...":
still_running = True
if not still_running:
print(f"Skipping, commit did not change - {last_commit_sha}")
continue
# It can come from a fork - we do not have UI tests for it
if branch_name == "master":
print("Ignoring a fork")
continue
last_commit_timestamp = get_commit_ts(last_commit_sha)
last_commit_datetime = datetime.fromtimestamp(last_commit_timestamp).strftime(
"%Y-%m-%d %H:%M"
)
pull_request_number = pr["number"]
pull_request_link = (
f"https://github.com/trezor/trezor-firmware/pull/{pull_request_number}"
)
branch_link = f"https://github.com/trezor/trezor-firmware/tree/{branch_name}"
yield BranchInfo(
name=branch_name,
branch_link=branch_link,
pull_request_number=pull_request_number,
pull_request_name=pr["title"],
pull_request_link=pull_request_link,
last_commit_sha=last_commit_sha,
last_commit_timestamp=last_commit_timestamp,
last_commit_datetime=last_commit_datetime,
job_infos={},
)