""" GitHub repository automation Creates/updates repositories, deploys to GitHub Pages """ from github import Github, Auth, GithubException import os import time import logging import requests logger = logging.getLogger(__name__) # To deploy the site on the git-pages def enable_github_pages(repo_full_name, branch="main"): """ Enable GitHub Pages for the repo via REST API """ token = os.getenv("GITHUB_TOKEN") url = f"https://api.github.com/repos/{repo_full_name}/pages" headers = { "Authorization": f"token {token}", "Accept": "application/vnd.github.v3+json" } payload = { "source": { "branch": branch, "path": "/" } } response = requests.post(url, json=payload, headers=headers) if response.status_code in [201, 204]: logger.info("✓ GitHub Pages enabled via REST API") elif response.status_code == 422: logger.info("GitHub Pages already enabled or validation error") else: logger.warning(f"Failed to enable GitHub Pages: {response.status_code} {response.text}") def deploy_to_github(task_name: str, html_content: str, readme_content: str, round_num: int = 1) -> tuple[str, str, str]: """ Complete GitHub deployment workflow Args: task_name: Unique task identifier (used as repo name) html_content: HTML code to deploy readme_content: README markdown content round_num: 1 for initial creation, 2 for updates Returns: Tuple of (repo_url, commit_sha, pages_url) """ # Authenticate auth = Auth.Token(os.getenv("GITHUB_TOKEN")) g = Github(auth=auth) try: user = g.get_user() repo_name = f"{task_name}" # Use task name directly logger.info(f"GitHub user: {user.login}") logger.info(f"Target repo: {repo_name}") if round_num == 1: # ROUND 1: Create new repository logger.info("Creating new repository...") repo = user.create_repo( name=repo_name, private=False, auto_init=True, license_template="mit", # Automatically adds MIT LICENSE description=f"LLM-generated application for task {task_name}" ) logger.info(f"✓ Repository created: {repo.html_url}") # Wait for repo to initialize time.sleep(3) # Add index.html (safe to create) html_result = repo.create_file( path="index.html", message="Initial commit - Add application", content=html_content ) commit_sha = html_result['commit'].sha logger.info("✓ Added index.html") # Check if README.md exists (likely created by auto_init=True) try: existing_readme = repo.get_contents("README.md") # If exists, update it repo.update_file( path="README.md", message="Update README documentation", content=readme_content, sha=existing_readme.sha ) logger.info("✓ Updated README.md") except GithubException as e: if e.status == 404: # README.md doesn't exist, create it repo.create_file( path="README.md", message="Add README documentation", content=readme_content ) logger.info("✓ Added README.md") else: logger.error(f"README.md handling error: {e}") # Enable GitHub Pages try: enable_github_pages(repo.full_name, branch="main") # logger.info("✓ GitHub Pages enabled") #is covered in the function except GithubException as e: if e.status == 409: logger.info("Pages already enabled") else: logger.warning(f"Pages enabling: {e}") else: # ROUND 2: Update existing repository logger.info("Updating existing repository...") repo = user.get_repo(repo_name) logger.info(f"✓ Found repository: {repo.html_url}") # Update index.html html_file = repo.get_contents("index.html") html_result = repo.update_file( path=html_file.path, message=f"Round {round_num} - Update application", content=html_content, sha=html_file.sha ) commit_sha = html_result['commit'].sha logger.info("✓ Updated index.html") # Update README.md readme_file = repo.get_contents("README.md") repo.update_file( path=readme_file.path, message=f"Round {round_num} - Update README", content=readme_content, sha=readme_file.sha ) logger.info("✓ Updated README.md") # Construct URLs repo_url = repo.html_url pages_url = f"https://{user.login}.github.io/{repo_name}/" logger.info(f"Deployment complete!") logger.info(f" Repository: {repo_url}") logger.info(f" Commit SHA: {commit_sha}") logger.info(f" Pages URL: {pages_url}") logger.info(f" ⚠️ Pages may take 2-5 minutes to be live") g.close() return repo_url, commit_sha, pages_url except GithubException as e: logger.error(f"GitHub API Error: {e.status} - {e.data}") g.close() raise except Exception as e: logger.error(f"Deployment error: {str(e)}") g.close() raise