import sys import signal import shutil import logging import time import os from datetime import datetime from typing import List, Dict import requests import gradio as gr import atexit import subprocess import webbrowser import urllib.parse import http.client import spaces import torch from accelerate import Accelerator import warnings warnings.filterwarnings('ignore', category=UserWarning, module='__main__') os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' @spaces.GPU def initialize_environment(): """Initialize application environment and configurations""" directories = ['logs', 'resolutions', 'repos'] for directory in directories: os.makedirs(directory, exist_ok=True) log_file = f"logs/github_bot_{datetime.now(). strftime('%Y%m%d_%H%M%S')}.log" logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(log_file), logging.StreamHandler() ] ) def handle_exception(exc_type, exc_value, exc_traceback): if issubclass(exc_type, KeyboardInterrupt): sys.__excepthook__(exc_type, exc_value, exc_traceback) return logging.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) sys.excepthook = handle_exception return logging.getLogger(__name__) logger = initialize_environment() class GitHubAPI: """GitHub API handler with rate limiting and error handling""" def __init__(self, token: str): self.token = token self.headers = { 'Authorization': f'token {token}', 'Accept': 'application/vnd.github.v3+json' } self.base_url = "https://api.github.com" def _check_rate_limit(self) -> bool: """Check and handle GitHub API rate limits""" try: response = requests.get(f"{self.base_url}/rate_limit", headers=self.headers) response.raise_for_status() limits = response.json() remaining = limits['resources']['core']['remaining'] reset_time = limits['resources']['core']['reset'] if remaining < 10: wait_time = max(0, reset_time - int(time.time())) if wait_time > 0: logger.warning(f"Rate limit nearly exceeded. Waiting {wait_time} seconds...") time.sleep(wait_time) return False return True except Exception as e: logger.error(f"Error checking rate limit: {str(e)}") return True def get_repository(self, owner: str, repo: str) -> Dict: """Get repository information""" try: response = requests.get(f"{self.base_url}/repos/{owner}/{repo}", headers=self.headers) response.raise_for_status() return response.json() except requests.HTTPError as e: logger.error(f"HTTP error getting repository info: {str(e)}") raise except Exception as e: logger.error(f"Error getting repository info: {str(e)}") raise def get_issues(self, owner: str, repo: str, state: str = 'open') -> List[Dict]: """Fetch repository issues""" if not self._check_rate_limit(): return [] try: response = requests.get(f"{self.base_url}/repos/{owner}/{repo}/issues", headers=self.headers, params={'state': state}) response.raise_for_status() issues = response.json() return [issue for issue in issues if 'pull_request' not in issue] except requests.HTTPError as e: logger.error(f"HTTP error fetching issues: {str(e)}") return [] except Exception as e: logger.error(f"Error fetching issues: {str(e)}") return [] class GitHubBot: """Main GitHub bot implementation""" def __init__(self): self.github_api = None def initialize_api(self, token: str ): """Initialize GitHub API with token""" self.github_api = GitHubAPI(token) def fetch_issues(self, token: str, username: str, repo: str) -> List[Dict]: """Fetch issues from GitHub repository""" try: self.initialize_api(token) return self.github_api.get_issues(username, repo) except Exception as e: logger.error(f"Error fetching issues: {str(e)}") return [] def resolve_issue(self, token: str, username: str, repo: str, issue_number: int, resolution: str, forked_repo: str) -> str: """Resolve a GitHub issue and submit PR.""" try: self.initialize_api(token) self.github_api.get_repository(username, repo) # Create resolution file timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") resolution_file = f"resolutions/resolution_{issue_number}_{timestamp}.md" with open(resolution_file, "w") as f: f.write(f"# Resolution for Issue #{issue_number}\n\n{resolution}") # Clone the forked repo subprocess.run(['git', 'clone', forked_repo, '/tmp/' + forked_repo.split('/')[-1]], check=True) # Change to the cloned directory os.chdir('/tmp/' + forked_repo.split('/')[-1]) # Assuming manual intervention now input(" Apply the fix manually and stage the changes (press ENTER)? ") # Commit and push the modifications subprocess.run(['git', 'add', '.'], check=True) subprocess.run(['git', 'commit', '-m', f"Resolved issue #{issue_number} ({urllib.parse.quote(resolution)})"], check=True) subprocess.run(['git', 'push', 'origin', 'HEAD'], check=True) # Open Pull Request page webbrowser.open(f'https://github.com/{forked_repo.split("/")[-1]}/compare/master...{username}:{forked_repo.split("/")[-1]}_resolved_issue_{issue_number}') return f"Resolution saved: {resolution_file}" except Exception as e: error_msg = f"Error resolving issue: {str(e)}" logger.error(error_msg) return error_msg def handle_issue_selection(token, username, repo, issue_number, resolution, forked_repo): bot = GitHubBot() result = bot.resolve_issue(token, username, repo, issue_number, resolution, forked_repo) return result custom_css = """ /* DaisyUI and Tailwind are loaded from CDN */ @import url('https://cdn.jsdelivr.net/npm/daisyui@3.1.0/dist/full.css'); @import url('https://cdn.tailwindcss.com'); /* Custom gradient background */ body { background: linear-gradient(to bottom right, #121212, #303030) !important; } /* Card styling */ .container { max-width: 800px; margin: 2rem auto; padding: 0 1rem; } .card { background: #2a2a2a; border-radius: 1rem; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); padding: 2rem; } /* Form controls */ .input, .select, .textarea { background: #363636; border: 1px solid #4a4a4a; color: #ffffff; border-radius: 0.5rem; padding: 0.75rem; width: 100%; margin-bottom: 1rem; } /* Buttons */ .button { width: 100%; padding: 0.75rem; border-radius: 0.5rem; font-weight: bold; cursor: pointer; transition: all 0.2s; } .button-primary { background: #570df8; color: white; } .button-success { background: #36d399; color: white; } /* Labels */ .label { color: #a3a3a3; margin-bottom: 0.5rem; display: block; } /* Output area */ .output-area { margin-top: 2rem; padding: 1rem; background: #363636; border-radius: 0.5rem; color: #ffffff; } """ def create_gradio_interface(): """Create and configure Gradio interface with custom styling""" bot = GitHubBot() with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as demo: gr.HTML("""