File size: 11,397 Bytes
95dd43a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5cf8dc3
95dd43a
 
 
5cf8dc3
 
95dd43a
 
5cf8dc3
 
95dd43a
5cf8dc3
 
 
95dd43a
 
5cf8dc3
 
 
 
 
 
95dd43a
5cf8dc3
95dd43a
 
5cf8dc3
 
95dd43a
5cf8dc3
 
 
 
 
 
 
 
 
95dd43a
5cf8dc3
95dd43a
 
5cf8dc3
 
95dd43a
5cf8dc3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95dd43a
5cf8dc3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95dd43a
 
 
30e5fc4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
"""GitHub-powered deployment agent for direct deployment actions."""

from __future__ import annotations

import os
from typing import Any, Dict, List, Optional

from enhanced_mcp_client import EnhancedMCPClient
from schemas import ReadinessPlan, ReadinessRequest


class DeploymentAgent:
    """Handles actual deployment actions via GitHub MCP."""

    def __init__(self):
        self.mcp_client = EnhancedMCPClient()

    async def prepare_deployment(
        self, request: ReadinessRequest, plan: ReadinessPlan
    ) -> Dict[str, Any]:
        """Prepare deployment configuration and actions."""
        github_repo = os.getenv("GITHUB_REPO")  # Format: owner/repo
        github_branch = os.getenv("GITHUB_BRANCH", "main")
        
        deployment_config = {
            "repo": github_repo,
            "branch": github_branch,
            "ready": False,
            "actions": []
        }

        if not github_repo:
            deployment_config["actions"].append({
                "type": "error",
                "message": "GITHUB_REPO not configured",
                "actionable": False
            })
            return deployment_config

        # Check if deployment workflow exists
        deployment_config["actions"].append({
            "type": "check_workflow",
            "message": f"Checking for deployment workflow in {github_repo}",
            "actionable": True
        })

        # Prepare deployment PR
        pr_title = f"Deploy: {request.release_goal}"
        pr_body = f"""
## Deployment Readiness Summary

**Project**: {request.project_name}
**Goal**: {request.release_goal}

### Checklist Items
{chr(10).join(f"- [ ] {item.title}" for item in plan.items[:5])}

### Code Summary
{request.code_summary[:200]}...

### Infrastructure Notes
{request.infra_notes or "None provided"}

---
*Generated by Deployment Readiness Copilot*
        """.strip()

        deployment_config["actions"].append({
            "type": "create_pr",
            "title": pr_title,
            "body": pr_body,
            "branch": f"deploy/{request.project_name.lower().replace(' ', '-')}",
            "actionable": True
        })

        # Trigger deployment workflow
        deployment_config["actions"].append({
            "type": "trigger_workflow",
            "workflow": ".github/workflows/deploy.yml",
            "branch": github_branch,
            "actionable": True
        })

        deployment_config["ready"] = True
        return deployment_config

    async def execute_deployment(
        self, deployment_config: Dict[str, Any]
    ) -> Dict[str, Any]:
        """Execute deployment actions via MCP to selected platform."""
        results = {
            "success": False,
            "actions_executed": [],
            "errors": [],
            "message": ""
        }

        platform = deployment_config.get("platform", "").lower()
        framework = deployment_config.get("framework", "").lower()
        repo = deployment_config.get("repo")

        if not platform or platform == "none":
            results["message"] = "No deployment platform selected"
            return results

        try:
            # Deploy to Vercel via MCP
            if platform == "vercel":
                if repo:
                    # Use Vercel MCP to deploy
                    deploy_result = await self.mcp_client.deploy_to_vercel(
                        repo=repo,
                        framework=framework
                    )
                    results["actions_executed"].append({
                        "type": "vercel_deploy",
                        "result": deploy_result
                    })
                    results["success"] = True
                    results["message"] = f"βœ… Deployed to Vercel (framework: {framework})"
                else:
                    results["message"] = "⚠️ GitHub repo required for Vercel deployment. Configure GITHUB_REPO."
            
            # Deploy to Netlify via MCP
            elif platform == "netlify":
                if repo:
                    deploy_result = await self.mcp_client.deploy_to_netlify(
                        repo=repo,
                        framework=framework
                    )
                    results["actions_executed"].append({
                        "type": "netlify_deploy",
                        "result": deploy_result
                    })
                    results["success"] = True
                    results["message"] = f"βœ… Deployed to Netlify (framework: {framework})"
                else:
                    results["message"] = "⚠️ GitHub repo required for Netlify deployment."
            
            # Deploy to AWS via MCP
            elif platform == "aws":
                deploy_result = await self.mcp_client.deploy_to_aws(
                    repo=repo,
                    framework=framework,
                    config=deployment_config
                )
                results["actions_executed"].append({
                    "type": "aws_deploy",
                    "result": deploy_result
                })
                results["success"] = True
                results["message"] = f"βœ… AWS deployment initiated (framework: {framework})"
            
            # Deploy to GCP via MCP
            elif platform == "gcp":
                deploy_result = await self.mcp_client.deploy_to_gcp(
                    repo=repo,
                    framework=framework,
                    config=deployment_config
                )
                results["actions_executed"].append({
                    "type": "gcp_deploy",
                    "result": deploy_result
                })
                results["success"] = True
                results["message"] = f"βœ… GCP deployment initiated (framework: {framework})"
            
            # Deploy to Azure via MCP
            elif platform == "azure":
                deploy_result = await self.mcp_client.deploy_to_azure(
                    repo=repo,
                    framework=framework,
                    config=deployment_config
                )
                results["actions_executed"].append({
                    "type": "azure_deploy",
                    "result": deploy_result
                })
                results["success"] = True
                results["message"] = f"βœ… Azure deployment initiated (framework: {framework})"
            
            # Deploy to Railway via MCP
            elif platform == "railway":
                deploy_result = await self.mcp_client.deploy_to_railway(
                    repo=repo,
                    framework=framework
                )
                results["actions_executed"].append({
                    "type": "railway_deploy",
                    "result": deploy_result
                })
                results["success"] = True
                results["message"] = f"βœ… Railway deployment initiated (framework: {framework})"
            
            # Deploy to Render via MCP
            elif platform == "render":
                deploy_result = await self.mcp_client.deploy_to_render(
                    repo=repo,
                    framework=framework
                )
                results["actions_executed"].append({
                    "type": "render_deploy",
                    "result": deploy_result
                })
                results["success"] = True
                results["message"] = f"βœ… Render deployment initiated (framework: {framework})"
            
            # Deploy to Fly.io via MCP
            elif platform == "fly.io":
                deploy_result = await self.mcp_client.deploy_to_flyio(
                    repo=repo,
                    framework=framework
                )
                results["actions_executed"].append({
                    "type": "flyio_deploy",
                    "result": deploy_result
                })
                results["success"] = True
                results["message"] = f"βœ… Fly.io deployment initiated (framework: {framework})"
            
            # Kubernetes deployment
            elif platform == "kubernetes":
                deploy_result = await self.mcp_client.deploy_to_kubernetes(
                    repo=repo,
                    framework=framework,
                    config=deployment_config
                )
                results["actions_executed"].append({
                    "type": "k8s_deploy",
                    "result": deploy_result
                })
                results["success"] = True
                results["message"] = f"βœ… Kubernetes deployment initiated (framework: {framework})"
            
            # Docker deployment
            elif platform == "docker":
                deploy_result = await self.mcp_client.deploy_to_docker(
                    repo=repo,
                    framework=framework,
                    config=deployment_config
                )
                results["actions_executed"].append({
                    "type": "docker_deploy",
                    "result": deploy_result
                })
                results["success"] = True
                results["message"] = f"βœ… Docker deployment initiated (framework: {framework})"
            
            else:
                results["message"] = f"⚠️ Platform '{platform}' deployment via MCP not yet implemented"
                results["errors"].append(f"Unsupported platform: {platform}")

        except Exception as e:
            results["errors"].append({
                "platform": platform,
                "error": str(e)
            })
            results["message"] = f"❌ Deployment error: {str(e)}"

        return results

    async def create_pull_request(self, title: str, body: str, branch: str, files: Dict[str, str]) -> str:
        """Create a GitHub Pull Request with the specified changes."""
        token = os.getenv("GITHUB_TOKEN")
        repo_name = os.getenv("GITHUB_REPO")
        
        if not token or not repo_name:
            return "❌ GITHUB_TOKEN or GITHUB_REPO not set."
            
        try:
            from github import Github
            g = Github(token)
            repo = g.get_repo(repo_name)
            
            # Get main branch
            source_branch = repo.get_branch("main")
            
            # Create new branch
            try:
                repo.create_git_ref(ref=f"refs/heads/{branch}", sha=source_branch.commit.sha)
            except Exception:
                # Branch might already exist
                pass
                
            # Commit files
            for file_path, content in files.items():
                try:
                    contents = repo.get_contents(file_path, ref=branch)
                    repo.update_file(contents.path, f"Update {file_path}", content, contents.sha, branch=branch)
                except Exception:
                    repo.create_file(file_path, f"Create {file_path}", content, branch=branch)
                    
            # Create PR
            pr = repo.create_pull(title=title, body=body, head=branch, base="main")
            return f"βœ… Pull Request Created: {pr.html_url}"
            
        except ImportError:
            return "❌ PyGithub not installed."
        except Exception as e:
            return f"❌ Failed to create PR: {str(e)}"