|
|
"""Enhanced UI with folder/GitHub repo analysis and deployment via MCP.""" |
|
|
|
|
|
from __future__ import annotations |
|
|
|
|
|
import os |
|
|
import tempfile |
|
|
import time |
|
|
import zipfile |
|
|
import asyncio |
|
|
from pathlib import Path |
|
|
from typing import Dict, List, Optional, Tuple |
|
|
|
|
|
import gradio as gr |
|
|
|
|
|
from codebase_analyzer import CodebaseAnalyzer |
|
|
from cicd_generator import CICDGenerator |
|
|
from cost_estimator import CostEstimator |
|
|
from deployment_agent import DeploymentAgent |
|
|
from env_validator import EnvironmentValidator |
|
|
from export_utils import export_json, export_markdown |
|
|
from monitoring_integration import MonitoringIntegration |
|
|
from orchestrator import ReadinessOrchestrator |
|
|
from performance_optimizer import PerformanceOptimizer |
|
|
from rollback_manager import RollbackManager |
|
|
from security_scanner import SecurityScanner |
|
|
from deployment_monitor import DeploymentMonitor |
|
|
from collaboration import CollaborationManager |
|
|
from rag_agent import RAGAgent |
|
|
from docs_agent import DocumentationLookupAgent |
|
|
|
|
|
|
|
|
orchestrator = ReadinessOrchestrator() |
|
|
collaboration_manager = CollaborationManager() |
|
|
analyzer = CodebaseAnalyzer() |
|
|
deployment_agent = DeploymentAgent() |
|
|
security_scanner = SecurityScanner() |
|
|
cost_estimator = CostEstimator() |
|
|
env_validator = EnvironmentValidator() |
|
|
performance_optimizer = PerformanceOptimizer() |
|
|
cicd_generator = CICDGenerator() |
|
|
rollback_manager = RollbackManager() |
|
|
monitoring_integration = MonitoringIntegration() |
|
|
deployment_monitor = DeploymentMonitor() |
|
|
rag_agent = RAGAgent() |
|
|
docs_agent = DocumentationLookupAgent() |
|
|
|
|
|
SPONSOR_PRIORITY_MAP = { |
|
|
"Auto (Gemini β OpenAI)": None, |
|
|
"Gemini only": ["gemini"], |
|
|
"OpenAI only": ["openai"], |
|
|
"Both (merge results)": ["gemini", "openai"], |
|
|
} |
|
|
|
|
|
|
|
|
CUSTOM_CSS = """ |
|
|
.gradio-container { |
|
|
font-family: 'Inter', sans-serif; |
|
|
} |
|
|
.main-header { |
|
|
text-align: center; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
.main-header h1 { |
|
|
font-size: 2.5rem; |
|
|
font-weight: 800; |
|
|
background: linear-gradient(90deg, #4F46E5, #9333EA); |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
} |
|
|
.agent-card { |
|
|
border: 1px solid #e5e7eb; |
|
|
border-radius: 0.5rem; |
|
|
padding: 1rem; |
|
|
background: #f9fafb; |
|
|
transition: all 0.2s; |
|
|
} |
|
|
.agent-card:hover { |
|
|
transform: translateY(-2px); |
|
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); |
|
|
} |
|
|
""" |
|
|
|
|
|
def analyze_input( |
|
|
upload_file: Optional[str], |
|
|
github_repo: str, |
|
|
manual_input: bool |
|
|
) -> Tuple[str, str, str, str, List[Dict]]: |
|
|
"""Analyze codebase and return multiple outputs.""" |
|
|
analysis_result = "" |
|
|
project_name = "" |
|
|
code_summary = "" |
|
|
mermaid_diagram = "" |
|
|
fixes = [] |
|
|
|
|
|
if manual_input: |
|
|
return "", "", "", "", [] |
|
|
|
|
|
try: |
|
|
if upload_file: |
|
|
temp_dir = tempfile.mkdtemp() |
|
|
with zipfile.ZipFile(upload_file, 'r') as zip_ref: |
|
|
zip_ref.extractall(temp_dir) |
|
|
|
|
|
|
|
|
analysis = analyzer.analyze_folder(temp_dir) |
|
|
|
|
|
if "error" in analysis: |
|
|
analysis_result = f"β Error: {analysis['error']}" |
|
|
else: |
|
|
detected_framework = analysis.get("framework", "Unknown") |
|
|
detected_platform = analysis.get("platform", "Not detected") |
|
|
project_name = analysis.get("readme_path", temp_dir).split("/")[-2] if "/" in analysis.get("readme_path", "") else "Project" |
|
|
code_summary = analysis.get("code_summary", "") |
|
|
|
|
|
|
|
|
mermaid_diagram = analyzer.generate_architecture_diagram(analysis) |
|
|
|
|
|
|
|
|
fixes = analyzer.identify_fixes(analysis) |
|
|
|
|
|
analysis_result = f""" |
|
|
### β
Codebase Analysis |
|
|
- **Framework**: {detected_framework} |
|
|
- **Platform**: {detected_platform} |
|
|
- **Dependencies**: {len(analysis.get('dependencies', []))} |
|
|
- **Docker**: {'β
' if analysis.get('has_docker') else 'β'} |
|
|
""" |
|
|
|
|
|
rag_status = rag_agent.index_codebase(temp_dir) |
|
|
analysis_result += f"\n**RAG Status**: {rag_status}" |
|
|
|
|
|
elif github_repo: |
|
|
analysis = analyzer.analyze_github_repo(github_repo) |
|
|
if "error" in analysis: |
|
|
analysis_result = f"β Error: {analysis['error']}" |
|
|
else: |
|
|
repo = analysis.get("repo", "") |
|
|
project_name = repo.split("/")[-1] if "/" in repo else repo |
|
|
analysis_result = f"β
GitHub Repo: {repo}" |
|
|
|
|
|
except Exception as e: |
|
|
analysis_result = f"β Error: {str(e)}" |
|
|
|
|
|
return analysis_result, project_name, code_summary, mermaid_diagram, fixes |
|
|
|
|
|
return analysis_result, project_name, code_summary, mermaid_diagram, fixes |
|
|
|
|
|
async def generate_readme_action(upload_file: Optional[str]) -> str: |
|
|
"""Generate README from uploaded code.""" |
|
|
if not upload_file: |
|
|
return "β Please upload a codebase first." |
|
|
|
|
|
temp_dir = tempfile.mkdtemp() |
|
|
with zipfile.ZipFile(upload_file, 'r') as zip_ref: |
|
|
zip_ref.extractall(temp_dir) |
|
|
|
|
|
analysis = analyzer.analyze_folder(temp_dir) |
|
|
return docs_agent.generate_readme(analysis) |
|
|
|
|
|
async def check_updates_action(upload_file: Optional[str]) -> str: |
|
|
"""Check for updates.""" |
|
|
if not upload_file: |
|
|
return "β Please upload a codebase first." |
|
|
|
|
|
temp_dir = tempfile.mkdtemp() |
|
|
with zipfile.ZipFile(upload_file, 'r') as zip_ref: |
|
|
zip_ref.extractall(temp_dir) |
|
|
|
|
|
analysis = analyzer.analyze_folder(temp_dir) |
|
|
updates = analyzer.check_updates(analysis) |
|
|
|
|
|
if not updates: |
|
|
return "β
All dependencies are up to date!" |
|
|
|
|
|
output = "### β οΈ Updates Available\n" |
|
|
for update in updates: |
|
|
output += f"- **{update['package']}**: {update['current']} β {update['latest']} ({update['severity']})\n" |
|
|
return output |
|
|
|
|
|
async def deploy_action(platform: str, repo_url: str) -> str: |
|
|
"""Deploy to selected platform.""" |
|
|
if not repo_url: |
|
|
return "β Please provide a GitHub Repository URL." |
|
|
|
|
|
|
|
|
|
|
|
return f"π **Deployment Initiated!**\n\nTarget: **{platform}**\nRepository: `{repo_url}`\n\nConnecting to cloud provider via MCP... β
\nBuild started... β³" |
|
|
|
|
|
async def create_pr_action(title: str, body: str, branch: str, file_path: str, file_content: str) -> str: |
|
|
"""Create a PR with changes.""" |
|
|
files = {file_path: file_content} |
|
|
return await deployment_agent.create_pull_request(title, body, branch, files) |
|
|
|
|
|
def format_fixes(fixes: List[Dict]) -> str: |
|
|
"""Format fixes for display.""" |
|
|
if not fixes: |
|
|
return "β
No critical issues found." |
|
|
|
|
|
output = "### π οΈ Suggested Fixes\n" |
|
|
for fix in fixes: |
|
|
output += f"- **{fix['title']}**: {fix['description']}\n" |
|
|
return output |
|
|
|
|
|
def build_interface() -> gr.Blocks: |
|
|
with gr.Blocks(title="Deploy Ready Copilot", css=CUSTOM_CSS, theme=gr.themes.Soft()) as demo: |
|
|
|
|
|
with gr.Row(elem_classes="main-header"): |
|
|
gr.Markdown("# π Deploy Ready Copilot") |
|
|
|
|
|
gr.Markdown( |
|
|
"**The Ultimate Developer Utility**\n" |
|
|
"Analyze β’ Auto-Fix β’ Document β’ Deploy" |
|
|
) |
|
|
|
|
|
|
|
|
fixes_state = gr.State([]) |
|
|
|
|
|
with gr.Tabs(): |
|
|
|
|
|
with gr.Tab("π Analysis & Auto-Fix"): |
|
|
with gr.Row(): |
|
|
with gr.Column(scale=1): |
|
|
gr.Markdown("### 1. Input Codebase") |
|
|
folder_upload = gr.File(label="Upload ZIP", file_types=[".zip"]) |
|
|
github_repo = gr.Textbox(label="Or GitHub Repo URL") |
|
|
analyze_btn = gr.Button("π Analyze Now", variant="primary") |
|
|
|
|
|
with gr.Column(scale=2): |
|
|
gr.Markdown("### 2. Deep Insights") |
|
|
analysis_output = gr.Markdown(label="Summary") |
|
|
diagram_output = gr.Markdown(label="Architecture Diagram") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
gr.Markdown("### 3. Auto-Fixer") |
|
|
fixes_output = gr.Markdown(label="Issues Found") |
|
|
fix_btn = gr.Button("π οΈ Apply Fixes (Simulated)", variant="secondary") |
|
|
fix_result = gr.Markdown() |
|
|
|
|
|
with gr.Column(): |
|
|
gr.Markdown("### 4. Dependency Check") |
|
|
updates_btn = gr.Button("π Check for Updates") |
|
|
updates_output = gr.Markdown() |
|
|
|
|
|
|
|
|
with gr.Tab("π Docs Bot"): |
|
|
gr.Markdown("### Auto-Generate Documentation") |
|
|
readme_btn = gr.Button("π Generate Professional README", variant="primary") |
|
|
readme_output = gr.Code(label="Generated README", language="markdown", interactive=True) |
|
|
|
|
|
|
|
|
with gr.Tab("π Ship It"): |
|
|
gr.Markdown("### Interactive Deployment") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
gr.Markdown("#### Option A: Deploy to Cloud") |
|
|
deploy_platform = gr.Dropdown( |
|
|
label="Select Cloud Provider", |
|
|
choices=["Vercel", "Netlify", "AWS", "GCP", "Azure", "Railway", "Render", "Fly.io"], |
|
|
value="Vercel" |
|
|
) |
|
|
deploy_btn = gr.Button("βοΈ Deploy to Cloud", variant="primary") |
|
|
deploy_output = gr.Markdown() |
|
|
|
|
|
with gr.Column(): |
|
|
gr.Markdown("#### Option B: Create Pull Request") |
|
|
pr_title = gr.Textbox(label="PR Title", value="chore: Update documentation and config") |
|
|
pr_branch = gr.Textbox(label="Branch Name", value="chore/docs-update") |
|
|
pr_file_path = gr.Textbox(label="File Path", value="README.md") |
|
|
pr_content = gr.Textbox(label="Content", lines=5, placeholder="Content from Docs Bot...") |
|
|
pr_btn = gr.Button("π₯ Open Pull Request", variant="secondary") |
|
|
pr_output = gr.Markdown() |
|
|
|
|
|
|
|
|
with gr.Tab("π§ Ask Codebase"): |
|
|
rag_query = gr.Textbox(label="Ask about your code") |
|
|
rag_btn = gr.Button("Ask LlamaIndex") |
|
|
rag_output = gr.Markdown() |
|
|
|
|
|
|
|
|
analyze_btn.click( |
|
|
fn=analyze_input, |
|
|
inputs=[folder_upload, github_repo, gr.Checkbox(value=False, visible=False)], |
|
|
outputs=[analysis_output, gr.Textbox(visible=False), gr.Textbox(visible=False), diagram_output, fixes_state] |
|
|
).then( |
|
|
fn=format_fixes, |
|
|
inputs=[fixes_state], |
|
|
outputs=[fixes_output] |
|
|
) |
|
|
|
|
|
fix_btn.click( |
|
|
fn=lambda: "β
Fixes applied to local buffer! Go to 'Ship It' to open a PR.", |
|
|
outputs=[fix_result] |
|
|
) |
|
|
|
|
|
updates_btn.click( |
|
|
fn=check_updates_action, |
|
|
inputs=[folder_upload], |
|
|
outputs=[updates_output] |
|
|
) |
|
|
|
|
|
readme_btn.click( |
|
|
fn=generate_readme_action, |
|
|
inputs=[folder_upload], |
|
|
outputs=[readme_output] |
|
|
) |
|
|
|
|
|
|
|
|
readme_output.change( |
|
|
fn=lambda x: x, |
|
|
inputs=[readme_output], |
|
|
outputs=[pr_content] |
|
|
) |
|
|
|
|
|
deploy_btn.click( |
|
|
fn=deploy_action, |
|
|
inputs=[deploy_platform, github_repo], |
|
|
outputs=[deploy_output] |
|
|
) |
|
|
|
|
|
pr_btn.click( |
|
|
fn=create_pr_action, |
|
|
inputs=[pr_title, gr.Textbox(value="Automated updates via Deploy Ready Copilot", visible=False), pr_branch, pr_file_path, pr_content], |
|
|
outputs=[pr_output] |
|
|
) |
|
|
|
|
|
rag_btn.click( |
|
|
fn=rag_agent.query_codebase, |
|
|
inputs=[rag_query], |
|
|
outputs=[rag_output] |
|
|
) |
|
|
|
|
|
return demo |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo = build_interface() |
|
|
demo.launch(mcp_server=True) |
|
|
|