diff --git a/actions/__init__.py b/actions/__init__.py index e83b3e4..eaff5ae 100644 --- a/actions/__init__.py +++ b/actions/__init__.py @@ -28,4 +28,4 @@ # ├── test_summarize_pr.py # └── ... -__version__ = "0.2.26" +__version__ = "0.2.27" diff --git a/actions/failed_scheduled_actions.py b/actions/failed_scheduled_actions.py index a94e651..95170d4 100644 --- a/actions/failed_scheduled_actions.py +++ b/actions/failed_scheduled_actions.py @@ -73,16 +73,20 @@ def github_get(path, params=None, token=None, allow_skip=False): "X-GitHub-Api-Version": "2022-11-28", }, ) - try: - with urllib.request.urlopen(request, timeout=60) as response: - return json.loads(response.read()) - except urllib.error.HTTPError as e: - body = e.read().decode(errors="ignore").lower() - rate_limited = e.code == 403 and (e.headers.get("X-RateLimit-Remaining") == "0" or "rate limit" in body) - if allow_skip and e.code in {403, 404} and not rate_limited: - print(f"Skipping {path}: {e.code}") - return None - raise + for attempt in range(3): + try: + with urllib.request.urlopen(request, timeout=60) as response: + return json.loads(response.read()) + except urllib.error.HTTPError as e: + if e.code in {500, 502, 503, 504} and attempt < 2: + time.sleep(2**attempt) + continue + body = e.read().decode(errors="ignore").lower() + rate_limited = e.code == 403 and (e.headers.get("X-RateLimit-Remaining") == "0" or "rate limit" in body) + if allow_skip and e.code in {403, 404} and not rate_limited: + print(f"Skipping {path}: {e.code}") + return None + raise def paginate(path, params=None, key=None, max_pages=100, token=None, allow_skip=False): diff --git a/tests/test_github_report.py b/tests/test_github_report.py index 7deeb90..e4a5f34 100644 --- a/tests/test_github_report.py +++ b/tests/test_github_report.py @@ -67,13 +67,16 @@ def test_github_get_fetches_json(monkeypatch): def fake_urlopen(request, timeout): requests.append((request.full_url, timeout, request.headers["Authorization"])) + if len(requests) == 1: + raise urllib.error.HTTPError("url", 504, "Gateway Timeout", {}, None) return Response() monkeypatch.setenv("GH_TOKEN", "token") monkeypatch.setattr(failed_scheduled_actions.urllib.request, "urlopen", fake_urlopen) + monkeypatch.setattr(failed_scheduled_actions.time, "sleep", lambda _: None) assert failed_scheduled_actions.github_get("/repos/ultralytics/actions", {"page": 1}) == {"ok": True} - assert requests == [("https://api.github.com/repos/ultralytics/actions?page=1", 60, "Bearer token")] + assert requests == [("https://api.github.com/repos/ultralytics/actions?page=1", 60, "Bearer token")] * 2 def test_github_get_skips_allowed_repo_errors(monkeypatch, capsys):