GitBot / app.py
acecalisto3's picture
Update app.py
0cdb48b verified
raw
history blame
8.06 kB
import gradio as gr
import os
import requests
from git import Repo, GitCommandError
from pathlib import Path
from datetime import datetime
import shutil
import time
# ========== Configuration ==========
REPO_OWNER = "enricoros"
REPO_NAME = "big-agi"
MIAGI_FORK = "https://github.com/Ig0tU/miagi.git"
WORKSPACE = Path("/tmp/issue_workspace")
WORKSPACE.mkdir(exist_ok=True)
# ========== Theme & Styling ==========
theme = gr.themes.Default(
primary_hue="emerald",
secondary_hue="zinc",
).set(
button_primary_background_fill="*primary_500",
button_primary_background_fill_hover="*primary_400",
button_primary_text_color="white",
block_label_background_fill="*primary_500",
block_label_text_color="white",
)
# ========== State Management ==========
class IssueManager:
def __init__(self):
self.issues = {}
self.last_fetched = None
self.current_issue = None
self.repo = None
def fetch_issues(self):
if self.last_fetched and (datetime.now() - self.last_fetched).seconds < 300:
return True
try:
response = requests.get(
f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/issues",
headers={"Authorization": f"Bearer {os.environ.get('GITHUB_TOKEN', '')}"}
)
response.raise_for_status()
self.issues = {issue['number']: issue for issue in response.json()}
self.last_fetched = datetime.now()
return True
except Exception as e:
print(f"Error fetching issues: {e}")
return False
issue_manager = IssueManager()
# ========== Core Functions ==========
def replicate_issue(issue_number):
try:
issue_number = int(issue_number)
if not issue_manager.fetch_issues():
return {"error": "⚠️ Failed to fetch issues from GitHub"}, None, None
if issue_number not in issue_manager.issues:
return {"error": f"❌ Issue #{issue_number} not found"}, None, None
issue = issue_manager.issues[issue_number]
repo_path = WORKSPACE / f"miagi-{issue_number}"
# Clone repository
try:
repo = Repo.clone_from(MIAGI_FORK, repo_path, branch="main")
except GitCommandError:
repo = Repo(repo_path)
# Create working branch
branch_name = f"issue-{issue_number}"
repo.git.checkout('-b', branch_name)
# Simulate issue replication
issues_dir = repo_path / "issues" / str(issue_number)
issues_dir.mkdir(parents=True, exist_ok=True)
(issues_dir / "replication.log").write_text(f"Replicated at {datetime.utcnow()} UTC")
issue_manager.repo = repo
issue_manager.current_issue = issue_number
return {
"success": f"πŸš€ Replicated issue #{issue_number} in branch '{branch_name}'"
}, issue["body"], gr.update(visible=True)
except Exception as e:
return {"error": f"β›” Critical error: {str(e)}"}, None, None
def resolve_issue(resolution_notes):
if not issue_manager.current_issue:
return {"error": "⚠️ No active issue selected"}, None
try:
repo = issue_manager.repo
issue_number = issue_manager.current_issue
resolution_dir = repo.working_dir / "issues" / str(issue_number)
# Create resolution files
timestamp = datetime.utcnow().strftime("%Y%m%d-%H%M%S")
(resolution_dir / f"resolution_{timestamp}.md").write_text(resolution_notes)
(resolution_dir / "RESOLVED").touch()
return {"success": "πŸ”§ Resolution draft saved locally"}, gr.update(visible=True)
except Exception as e:
return {"error": f"β›” Resolution failed: {str(e)}"}, None
def submit_resolution():
if not issue_manager.current_issue:
return {"error": "⚠️ No active issue selected"}
try:
repo = issue_manager.repo
issue_number = issue_manager.current_issue
# Stage changes
repo.git.add(all=True)
# Commit
commit_message = f"Resolve #{issue_number}: {issue_manager.issues[issue_number]['title']}"
repo.index.commit(commit_message)
# Push
origin = repo.remote(name='origin')
origin.push(refspec=f"issue-{issue_number}:issue-{issue_number}")
# Create PR
pr_url = f"https://github.com/Ig0tU/miagi/compare/issue-{issue_number}?expand=1"
return {
"success": f"πŸš€ Resolution submitted!\n\n[Review PR]({pr_url})",
"pr_url": pr_url
}
except GitCommandError as e:
return {"error": f"β›” Git operation failed: {str(e)}"}
except Exception as e:
return {"error": f"β›” Submission failed: {str(e)}"}
# ========== UI Components ==========
def create_header():
with gr.Row():
gr.Markdown("""
# πŸš€ Issue Resolution Workshop
### ⚑ Power Tools for GitHub Issue Management
""")
gr.Image(value="https://img.icons8.com/3d-fluency/94/github.png", width=94, height=94)
def create_workflow_tabs():
with gr.Tabs() as tabs:
with gr.TabItem("πŸ” Investigate", id=1):
with gr.Row():
with gr.Column(scale=1):
issue_input = gr.Number(label="ISSUE NUMBER", precision=0)
gr.Button("πŸ“‘ Sync GitHub Issues", variant="secondary").click(
fn=lambda: issue_manager.fetch_issues(),
outputs=None
)
with gr.Column(scale=2):
status_output = gr.JSON(label="STATUS")
replicate_btn = gr.Button("⚑ Replicate Issue", variant="primary")
with gr.TabItem("πŸ”§ Resolve", id=2):
with gr.Row():
with gr.Column():
issue_desc = gr.Markdown("### Issue details will appear here")
resolution_input = gr.Textbox(label="Resolution Notes", lines=8,
placeholder="Describe your solution...")
resolve_btn = gr.Button("πŸ’Ύ Save Resolution", variant="primary")
with gr.Column():
resolution_proof = gr.FileExplorer(label="Resolution Artifacts")
with gr.TabItem("πŸš€ Deploy", id=3):
with gr.Row():
with gr.Column():
gr.Markdown("### Deployment Checklist")
gr.CheckboxGroup(["βœ… Tests passing", "βœ… Code reviewed", "βœ… Documentation updated"])
deploy_btn = gr.Button("πŸ”₯ Submit Resolution", variant="primary")
with gr.Column():
pr_output = gr.Markdown()
return (issue_input, replicate_btn, status_output, issue_desc,
resolution_input, resolve_btn, deploy_btn, pr_output)
# ========== App Assembly ==========
with gr.Blocks(theme=theme, css="footer {visibility: hidden}") as app:
create_header()
components = create_workflow_tabs()
(issue_input, replicate_btn, status_output, issue_desc,
resolution_input, resolve_btn, deploy_btn, pr_output) = components
# Event handlers
replicate_event = replicate_btn.click(
fn=replicate_issue,
inputs=issue_input,
outputs=[status_output, issue_desc, gr.Tabs(selected=1)]
)
resolve_event = resolve_btn.click(
fn=resolve_issue,
inputs=resolution_input,
outputs=[status_output, deploy_btn]
)
deploy_event = deploy_btn.click(
fn=submit_resolution,
outputs=[status_output, pr_output]
)
# Progress animations
replicate_event.then(
fn=lambda: gr.update(visible=True),
outputs=resolve_btn
)
# ========== Execution ==========
if __name__ == "__main__":
app.launch(server_port=7860, share=True)