Skip to content

Commit 2065058

Browse files
authored
fix: use GITHUB_TOKEN in get_latest_release to avoid rate limits (#428)
1 parent ab18427 commit 2065058

2 files changed

Lines changed: 61 additions & 1 deletion

File tree

comfy_cli/command/install.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,16 @@ def get_latest_release(repo_owner: str, repo_name: str) -> GithubRelease | None:
476476
"""
477477
url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases/latest"
478478

479+
headers = {}
480+
if github_token := os.getenv("GITHUB_TOKEN"):
481+
headers["Authorization"] = f"Bearer {github_token}"
482+
479483
try:
480-
response = requests.get(url, timeout=5)
484+
response = requests.get(url, headers=headers, timeout=5)
485+
486+
if response.status_code in (403, 429):
487+
handle_github_rate_limit(response)
488+
481489
response.raise_for_status()
482490

483491
data = response.json()

tests/comfy_cli/command/github/test_pr.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
PRInfo,
1212
fetch_pr_info,
1313
find_pr_by_branch,
14+
get_latest_release,
1415
handle_github_rate_limit,
1516
handle_pr_checkout,
1617
parse_pr_reference,
@@ -445,6 +446,57 @@ def test_checkout_pr_remote_already_exists(self, mock_getcwd, mock_chdir, mock_s
445446
assert mock_subprocess.call_count == 3
446447

447448

449+
class TestGetLatestRelease:
450+
"""Test get_latest_release GitHub API calls"""
451+
452+
@patch("requests.get")
453+
def test_sends_auth_header_when_token_set(self, mock_get):
454+
"""Ensure GITHUB_TOKEN is sent as Bearer auth to avoid rate limits (issue #425)"""
455+
mock_response = Mock()
456+
mock_response.status_code = 200
457+
mock_response.json.return_value = {
458+
"tag_name": "v0.18.2",
459+
"zipball_url": "https://github.com/comfyanonymous/ComfyUI/archive/v0.18.2.zip",
460+
}
461+
mock_get.return_value = mock_response
462+
463+
with patch.dict("os.environ", {"GITHUB_TOKEN": "ghp_test123"}):
464+
result = get_latest_release("comfyanonymous", "ComfyUI")
465+
466+
headers = mock_get.call_args.kwargs.get("headers", {})
467+
assert headers["Authorization"] == "Bearer ghp_test123"
468+
assert result is not None
469+
assert result["tag"] == "v0.18.2"
470+
471+
@patch("requests.get")
472+
def test_no_auth_header_without_token(self, mock_get):
473+
"""Without GITHUB_TOKEN the request has no Authorization header"""
474+
mock_response = Mock()
475+
mock_response.status_code = 200
476+
mock_response.json.return_value = {
477+
"tag_name": "v0.18.2",
478+
"zipball_url": "https://github.com/comfyanonymous/ComfyUI/archive/v0.18.2.zip",
479+
}
480+
mock_get.return_value = mock_response
481+
482+
with patch.dict("os.environ", {}, clear=True):
483+
get_latest_release("comfyanonymous", "ComfyUI")
484+
485+
headers = mock_get.call_args.kwargs.get("headers", {})
486+
assert "Authorization" not in headers
487+
488+
@patch("requests.get")
489+
def test_rate_limit_raises_error(self, mock_get):
490+
"""A 403 with exhausted rate limit raises GitHubRateLimitError"""
491+
mock_response = Mock()
492+
mock_response.status_code = 403
493+
mock_response.headers = {"x-ratelimit-remaining": "0", "x-ratelimit-reset": "1700000000"}
494+
mock_get.return_value = mock_response
495+
496+
with pytest.raises(GitHubRateLimitError):
497+
get_latest_release("comfyanonymous", "ComfyUI")
498+
499+
448500
class TestHandleGithubRateLimit:
449501
def test_primary_rate_limit_message_format(self):
450502
"""Verify the error message does not contain stray characters."""

0 commit comments

Comments
 (0)