|
"""
|
|
システム自動化モジュール
|
|
GPT-ENGINEERで生成されたシステムをGitHubにアップし、
|
|
Controller/Routerを自動認識する機能
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
import json
|
|
import requests
|
|
from pathlib import Path
|
|
from typing import Dict, List, Optional
|
|
import tempfile
|
|
import shutil
|
|
|
|
class SystemAutomation:
|
|
"""システム自動化クラス"""
|
|
|
|
def __init__(self, github_token: str, base_workspace: str = "/workspaces/fastapi_django_main_live"):
|
|
self.github_token = github_token
|
|
self.base_workspace = Path(base_workspace)
|
|
self.controllers_dir = self.base_workspace / "controllers"
|
|
self.routers_dir = self.base_workspace / "routers"
|
|
|
|
def create_github_repository(self, repo_name: str, description: str = "") -> Dict:
|
|
"""GitHubリポジトリを作成"""
|
|
try:
|
|
headers = {
|
|
'Authorization': f'token {self.github_token}',
|
|
'Accept': 'application/vnd.github.v3+json'
|
|
}
|
|
|
|
data = {
|
|
'name': repo_name,
|
|
'description': description,
|
|
'private': False,
|
|
'auto_init': True
|
|
}
|
|
|
|
response = requests.post(
|
|
'https://api.github.com/user/repos',
|
|
headers=headers,
|
|
json=data
|
|
)
|
|
|
|
if response.status_code == 201:
|
|
repo_data = response.json()
|
|
return {
|
|
'success': True,
|
|
'url': repo_data['html_url'],
|
|
'clone_url': repo_data['clone_url'],
|
|
'ssh_url': repo_data['ssh_url']
|
|
}
|
|
else:
|
|
return {
|
|
'success': False,
|
|
'error': f"GitHub API エラー: {response.status_code} - {response.text}"
|
|
}
|
|
|
|
except Exception as e:
|
|
return {
|
|
'success': False,
|
|
'error': f"リポジトリ作成エラー: {str(e)}"
|
|
}
|
|
|
|
def push_to_github(self, local_path: str, repo_url: str, commit_message: str = "Initial commit") -> Dict:
|
|
"""ローカルのコードをGitHubにプッシュ"""
|
|
try:
|
|
local_path = Path(local_path)
|
|
|
|
if not local_path.exists():
|
|
return {'success': False, 'error': 'ローカルパスが存在しません'}
|
|
|
|
|
|
subprocess.run(['git', 'init'], cwd=local_path, check=True)
|
|
subprocess.run(['git', 'add', '.'], cwd=local_path, check=True)
|
|
subprocess.run(['git', 'commit', '-m', commit_message], cwd=local_path, check=True)
|
|
subprocess.run(['git', 'branch', '-M', 'main'], cwd=local_path, check=True)
|
|
subprocess.run(['git', 'remote', 'add', 'origin', repo_url], cwd=local_path, check=True)
|
|
subprocess.run(['git', 'push', '-u', 'origin', 'main'], cwd=local_path, check=True)
|
|
|
|
return {
|
|
'success': True,
|
|
'message': 'GitHubプッシュ完了'
|
|
}
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
return {
|
|
'success': False,
|
|
'error': f"Git操作エラー: {str(e)}"
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
'success': False,
|
|
'error': f"プッシュエラー: {str(e)}"
|
|
}
|
|
|
|
def scan_for_controllers(self, generated_path: str) -> List[Dict]:
|
|
"""生成されたコードからController/Routerを検索"""
|
|
controllers = []
|
|
generated_path = Path(generated_path)
|
|
|
|
if not generated_path.exists():
|
|
return controllers
|
|
|
|
|
|
for file_path in generated_path.rglob("*.py"):
|
|
try:
|
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
|
|
if 'APIRouter' in content or 'router' in content.lower():
|
|
controllers.append({
|
|
'type': 'fastapi_router',
|
|
'file': str(file_path),
|
|
'name': file_path.stem,
|
|
'content_preview': content[:200] + '...' if len(content) > 200 else content
|
|
})
|
|
|
|
|
|
if 'gradio_interface' in content or 'gr.Blocks' in content:
|
|
controllers.append({
|
|
'type': 'gradio_interface',
|
|
'file': str(file_path),
|
|
'name': file_path.stem,
|
|
'content_preview': content[:200] + '...' if len(content) > 200 else content
|
|
})
|
|
|
|
|
|
if 'django' in content.lower() and ('def ' in content or 'class ' in content):
|
|
controllers.append({
|
|
'type': 'django_view',
|
|
'file': str(file_path),
|
|
'name': file_path.stem,
|
|
'content_preview': content[:200] + '...' if len(content) > 200 else content
|
|
})
|
|
|
|
except Exception as e:
|
|
print(f"ファイル読み込みエラー {file_path}: {e}")
|
|
|
|
return controllers
|
|
|
|
def auto_integrate_controllers(self, controllers: List[Dict]) -> Dict:
|
|
"""Controller/Routerを自動統合"""
|
|
results = {
|
|
'integrated': [],
|
|
'errors': []
|
|
}
|
|
|
|
for controller in controllers:
|
|
try:
|
|
source_file = Path(controller['file'])
|
|
controller_type = controller['type']
|
|
|
|
if controller_type == 'fastapi_router':
|
|
|
|
dest_dir = self.routers_dir
|
|
dest_file = dest_dir / f"auto_{controller['name']}.py"
|
|
|
|
elif controller_type == 'gradio_interface':
|
|
|
|
dest_dir = self.controllers_dir / "gradio_auto"
|
|
dest_dir.mkdir(exist_ok=True)
|
|
dest_file = dest_dir / f"{controller['name']}.py"
|
|
|
|
elif controller_type == 'django_view':
|
|
|
|
dest_dir = self.controllers_dir / "django_auto"
|
|
dest_dir.mkdir(exist_ok=True)
|
|
dest_file = dest_dir / f"{controller['name']}.py"
|
|
|
|
else:
|
|
continue
|
|
|
|
|
|
dest_dir.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(source_file, dest_file)
|
|
|
|
results['integrated'].append({
|
|
'type': controller_type,
|
|
'source': str(source_file),
|
|
'destination': str(dest_file),
|
|
'name': controller['name']
|
|
})
|
|
|
|
except Exception as e:
|
|
results['errors'].append({
|
|
'controller': controller['name'],
|
|
'error': str(e)
|
|
})
|
|
|
|
return results
|
|
|
|
def full_automation_pipeline(self,
|
|
generated_folder: str,
|
|
repo_name: str,
|
|
description: str = "",
|
|
commit_message: str = "Generated system") -> Dict:
|
|
"""完全自動化パイプライン"""
|
|
pipeline_results = {
|
|
'github_repo': None,
|
|
'github_push': None,
|
|
'controllers_found': [],
|
|
'integration_results': None,
|
|
'success': False
|
|
}
|
|
|
|
try:
|
|
|
|
print(f"🚀 GitHubリポジトリ作成: {repo_name}")
|
|
repo_result = self.create_github_repository(repo_name, description)
|
|
pipeline_results['github_repo'] = repo_result
|
|
|
|
if not repo_result['success']:
|
|
return pipeline_results
|
|
|
|
|
|
print(f"📤 GitHubにプッシュ中...")
|
|
push_result = self.push_to_github(
|
|
generated_folder,
|
|
repo_result['clone_url'],
|
|
commit_message
|
|
)
|
|
pipeline_results['github_push'] = push_result
|
|
|
|
|
|
print(f"🔍 Controller/Router検索中...")
|
|
controllers = self.scan_for_controllers(generated_folder)
|
|
pipeline_results['controllers_found'] = controllers
|
|
|
|
|
|
if controllers:
|
|
print(f"🔧 Controller/Router自動統合中...")
|
|
integration_result = self.auto_integrate_controllers(controllers)
|
|
pipeline_results['integration_results'] = integration_result
|
|
|
|
pipeline_results['success'] = True
|
|
return pipeline_results
|
|
|
|
except Exception as e:
|
|
pipeline_results['error'] = str(e)
|
|
return pipeline_results
|
|
|
|
|
|
def create_system_automation_interface():
|
|
"""システム自動化のGradio インターフェース"""
|
|
import gradio as gr
|
|
|
|
def run_automation_pipeline(github_token, repo_name, generated_folder, description):
|
|
if not github_token or not repo_name or not generated_folder:
|
|
return "❌ 必須項目を入力してください", ""
|
|
|
|
automation = SystemAutomation(github_token)
|
|
result = automation.full_automation_pipeline(
|
|
generated_folder,
|
|
repo_name,
|
|
description
|
|
)
|
|
|
|
if result['success']:
|
|
summary = f"""✅ 自動化パイプライン完了!
|
|
|
|
🔗 GitHub リポジトリ: {result['github_repo']['url']}
|
|
📤 プッシュ: {'成功' if result['github_push']['success'] else '失敗'}
|
|
🔍 検出されたController: {len(result['controllers_found'])}件
|
|
🔧 統合結果: {len(result['integration_results']['integrated']) if result['integration_results'] else 0}件統合済み
|
|
"""
|
|
|
|
details = json.dumps(result, indent=2, ensure_ascii=False)
|
|
return summary, details
|
|
else:
|
|
return f"❌ エラー: {result.get('error', '不明なエラー')}", json.dumps(result, indent=2, ensure_ascii=False)
|
|
|
|
with gr.Blocks(title="🚀 システム自動化") as interface:
|
|
gr.Markdown("# 🚀 システム自動化パイプライン")
|
|
gr.Markdown("生成されたシステムを自動でGitHubにアップし、Controller/Routerを統合します")
|
|
|
|
with gr.Row():
|
|
with gr.Column():
|
|
github_token_input = gr.Textbox(
|
|
label="GitHub Token",
|
|
type="password",
|
|
placeholder="ghp_xxxxxxxxxxxxxxxxxxxx"
|
|
)
|
|
repo_name_input = gr.Textbox(
|
|
label="リポジトリ名",
|
|
placeholder="my-generated-system"
|
|
)
|
|
generated_folder_input = gr.Textbox(
|
|
label="生成されたフォルダパス",
|
|
placeholder="/path/to/generated/system"
|
|
)
|
|
description_input = gr.Textbox(
|
|
label="リポジトリ説明",
|
|
placeholder="GPT-ENGINEERで生成されたシステム"
|
|
)
|
|
|
|
run_button = gr.Button("🚀 自動化実行", variant="primary")
|
|
|
|
with gr.Column():
|
|
result_summary = gr.Textbox(
|
|
label="実行結果サマリー",
|
|
lines=10,
|
|
interactive=False
|
|
)
|
|
result_details = gr.Textbox(
|
|
label="詳細結果 (JSON)",
|
|
lines=15,
|
|
interactive=False
|
|
)
|
|
|
|
run_button.click(
|
|
fn=run_automation_pipeline,
|
|
inputs=[github_token_input, repo_name_input, generated_folder_input, description_input],
|
|
outputs=[result_summary, result_details]
|
|
)
|
|
|
|
return interface
|
|
|
|
|
|
system_automation_interface = create_system_automation_interface()
|
|
|