Skip to content

Commit 4e24ee2

Browse files
committed
Downalod files from GitHub
1 parent 545eb70 commit 4e24ee2

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

src/redis_release/github_client_async.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Async GitHub API client for workflow operations."""
22

3+
import base64
34
import io
45
import json
56
import logging
@@ -603,6 +604,69 @@ def _extract_uuid(self, text: str) -> Optional[str]:
603604
uuid_match = re.search(uuid_pattern, text, re.IGNORECASE)
604605
return uuid_match.group() if uuid_match else None
605606

607+
async def download_file(
608+
self, repo: str, file_path: str, ref: str = "main"
609+
) -> Optional[str]:
610+
"""Download a specific file from a repository at a specific branch/ref.
611+
612+
Args:
613+
repo: Repository name (e.g., "redis/redis")
614+
file_path: Path to the file in the repository (e.g., "config.yaml", "src/main.py")
615+
ref: Git reference (branch, tag, or commit SHA) to download from (default: "main")
616+
617+
Returns:
618+
File content as a string, or None if the file is not found or an error occurs
619+
"""
620+
url = f"https://api.github.com/repos/{repo}/contents/{file_path}"
621+
headers = {
622+
"Authorization": f"Bearer {self.token}",
623+
"Accept": "application/vnd.github.v3+json",
624+
"X-GitHub-Api-Version": "2022-11-28",
625+
}
626+
params = {"ref": ref}
627+
628+
try:
629+
logger.debug(
630+
f"[blue]Downloading file[/blue] {file_path} from {repo} at ref {ref}"
631+
)
632+
633+
data = await self.github_request(
634+
url=url,
635+
headers=headers,
636+
method="GET",
637+
params=params,
638+
timeout=30,
639+
error_context=f"download file {file_path}",
640+
)
641+
642+
# GitHub API returns file content base64-encoded
643+
if "content" in data and data.get("encoding") == "base64":
644+
content = base64.b64decode(data["content"]).decode("utf-8")
645+
logger.debug(
646+
f"[green]Successfully downloaded {file_path}[/green] ({len(content)} bytes)"
647+
)
648+
return content
649+
else:
650+
logger.error(
651+
f"[red]Unexpected response format for file {file_path}[/red]"
652+
)
653+
return None
654+
655+
except aiohttp.ClientResponseError as e:
656+
if e.status == 404:
657+
logger.warning(
658+
f"[yellow]File {file_path} not found in {repo} at ref {ref}[/yellow]"
659+
)
660+
else:
661+
logger.error(f"[red]Failed to download file {file_path}: {e}[/red]")
662+
return None
663+
except aiohttp.ClientError as e:
664+
logger.error(f"[red]Failed to download file {file_path}: {e}[/red]")
665+
return None
666+
except Exception as e:
667+
logger.error(f"[red]Error downloading file {file_path}: {e}[/red]")
668+
return None
669+
606670
async def list_remote_branches(
607671
self, repo: str, pattern: Optional[str] = None
608672
) -> List[str]:

0 commit comments

Comments
 (0)