Commit
·
96c4d0f
1
Parent(s):
a42b16d
Add team collaboration features (10th improvement)
Browse files- Review sessions with stakeholder approvals
- Comments and feedback system
- Approval workflow tracking
- Team review status monitoring
- Complete all 10 utility improvements
- app.py +20 -3
- collaboration.py +127 -0
app.py
CHANGED
|
@@ -23,8 +23,10 @@ from performance_optimizer import PerformanceOptimizer
|
|
| 23 |
from rollback_manager import RollbackManager
|
| 24 |
from security_scanner import SecurityScanner
|
| 25 |
from deployment_monitor import DeploymentMonitor
|
|
|
|
| 26 |
|
| 27 |
orchestrator = ReadinessOrchestrator()
|
|
|
|
| 28 |
analyzer = CodebaseAnalyzer()
|
| 29 |
deployment_agent = DeploymentAgent()
|
| 30 |
security_scanner = SecurityScanner()
|
|
@@ -233,16 +235,25 @@ def run_full_pipeline(
|
|
| 233 |
"""
|
| 234 |
|
| 235 |
# Step 2: Run readiness pipeline
|
|
|
|
| 236 |
payload = {
|
| 237 |
"project_name": project_name or "Unnamed Service",
|
| 238 |
"release_goal": release_goal or "Deploy to production",
|
| 239 |
"code_summary": code_summary or "Codebase analysis complete",
|
| 240 |
"infra_notes": infra_notes or None,
|
| 241 |
-
"stakeholders":
|
| 242 |
}
|
| 243 |
|
| 244 |
result = orchestrator.run_dict(payload)
|
| 245 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 246 |
# Step 3: Update README if requested
|
| 247 |
readme_update_status = ""
|
| 248 |
if update_readme and upload_folder:
|
|
@@ -398,6 +409,7 @@ def run_full_pipeline(
|
|
| 398 |
cicd_config or "No CI/CD config generated",
|
| 399 |
rollback_plan or "No rollback plan generated",
|
| 400 |
monitoring_setup or "No monitoring setup available",
|
|
|
|
| 401 |
json_export,
|
| 402 |
markdown_export
|
| 403 |
)
|
|
@@ -548,8 +560,12 @@ def build_interface() -> gr.Blocks:
|
|
| 548 |
rollback_output = gr.Textbox(label="Rollback Strategy", lines=6, interactive=False)
|
| 549 |
|
| 550 |
with gr.Row():
|
| 551 |
-
gr.Markdown("### 📊 Monitoring")
|
| 552 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 553 |
|
| 554 |
# Exports
|
| 555 |
with gr.Row():
|
|
@@ -593,6 +609,7 @@ def build_interface() -> gr.Blocks:
|
|
| 593 |
cicd_output,
|
| 594 |
rollback_output,
|
| 595 |
monitoring_output,
|
|
|
|
| 596 |
json_export,
|
| 597 |
markdown_export
|
| 598 |
]
|
|
|
|
| 23 |
from rollback_manager import RollbackManager
|
| 24 |
from security_scanner import SecurityScanner
|
| 25 |
from deployment_monitor import DeploymentMonitor
|
| 26 |
+
from collaboration import CollaborationManager
|
| 27 |
|
| 28 |
orchestrator = ReadinessOrchestrator()
|
| 29 |
+
collaboration_manager = CollaborationManager()
|
| 30 |
analyzer = CodebaseAnalyzer()
|
| 31 |
deployment_agent = DeploymentAgent()
|
| 32 |
security_scanner = SecurityScanner()
|
|
|
|
| 235 |
"""
|
| 236 |
|
| 237 |
# Step 2: Run readiness pipeline
|
| 238 |
+
stakeholders_list = [s.strip() for s in stakeholders.split(",") if s.strip()] if stakeholders else ["eng"]
|
| 239 |
payload = {
|
| 240 |
"project_name": project_name or "Unnamed Service",
|
| 241 |
"release_goal": release_goal or "Deploy to production",
|
| 242 |
"code_summary": code_summary or "Codebase analysis complete",
|
| 243 |
"infra_notes": infra_notes or None,
|
| 244 |
+
"stakeholders": stakeholders_list,
|
| 245 |
}
|
| 246 |
|
| 247 |
result = orchestrator.run_dict(payload)
|
| 248 |
|
| 249 |
+
# Create collaboration review
|
| 250 |
+
review_id = f"{project_name}-{int(time.time())}"
|
| 251 |
+
collaboration_review = collaboration_manager.create_review(
|
| 252 |
+
review_id,
|
| 253 |
+
project_name or "Unnamed Service",
|
| 254 |
+
stakeholders_list
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
# Step 3: Update README if requested
|
| 258 |
readme_update_status = ""
|
| 259 |
if update_readme and upload_folder:
|
|
|
|
| 409 |
cicd_config or "No CI/CD config generated",
|
| 410 |
rollback_plan or "No rollback plan generated",
|
| 411 |
monitoring_setup or "No monitoring setup available",
|
| 412 |
+
f"**Review ID**: {review_id}\n**Status**: {collaboration_review['status']}\n**Stakeholders**: {', '.join(stakeholders_list)}\n**Ready for approval**: Yes" if collaboration_review else "No collaboration review",
|
| 413 |
json_export,
|
| 414 |
markdown_export
|
| 415 |
)
|
|
|
|
| 560 |
rollback_output = gr.Textbox(label="Rollback Strategy", lines=6, interactive=False)
|
| 561 |
|
| 562 |
with gr.Row():
|
| 563 |
+
gr.Markdown("### 📊 Monitoring & Collaboration")
|
| 564 |
+
with gr.Row():
|
| 565 |
+
with gr.Column():
|
| 566 |
+
monitoring_output = gr.Textbox(label="Monitoring Setup", lines=6, interactive=False)
|
| 567 |
+
with gr.Column():
|
| 568 |
+
collaboration_output = gr.Textbox(label="Team Review", lines=6, interactive=False)
|
| 569 |
|
| 570 |
# Exports
|
| 571 |
with gr.Row():
|
|
|
|
| 609 |
cicd_output,
|
| 610 |
rollback_output,
|
| 611 |
monitoring_output,
|
| 612 |
+
collaboration_output,
|
| 613 |
json_export,
|
| 614 |
markdown_export
|
| 615 |
]
|
collaboration.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Team collaboration features for deployment reviews."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import time
|
| 6 |
+
from dataclasses import dataclass, field
|
| 7 |
+
from typing import Any, Dict, List, Optional
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
@dataclass
|
| 11 |
+
class ReviewComment:
|
| 12 |
+
"""A comment on a deployment readiness review."""
|
| 13 |
+
author: str
|
| 14 |
+
comment: str
|
| 15 |
+
timestamp: float
|
| 16 |
+
category: str = "general"
|
| 17 |
+
resolved: bool = False
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@dataclass
|
| 21 |
+
class Approval:
|
| 22 |
+
"""An approval from a stakeholder."""
|
| 23 |
+
approver: str
|
| 24 |
+
role: str
|
| 25 |
+
approved: bool
|
| 26 |
+
timestamp: float
|
| 27 |
+
notes: Optional[str] = None
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class CollaborationManager:
|
| 31 |
+
"""Manages team collaboration for deployment reviews."""
|
| 32 |
+
|
| 33 |
+
def __init__(self):
|
| 34 |
+
self.reviews: Dict[str, Dict[str, Any]] = {}
|
| 35 |
+
|
| 36 |
+
def create_review(
|
| 37 |
+
self,
|
| 38 |
+
review_id: str,
|
| 39 |
+
project_name: str,
|
| 40 |
+
stakeholders: List[str]
|
| 41 |
+
) -> Dict[str, Any]:
|
| 42 |
+
"""Create a new review session."""
|
| 43 |
+
review = {
|
| 44 |
+
"id": review_id,
|
| 45 |
+
"project_name": project_name,
|
| 46 |
+
"stakeholders": stakeholders,
|
| 47 |
+
"comments": [],
|
| 48 |
+
"approvals": [],
|
| 49 |
+
"status": "pending",
|
| 50 |
+
"created_at": time.time()
|
| 51 |
+
}
|
| 52 |
+
self.reviews[review_id] = review
|
| 53 |
+
return review
|
| 54 |
+
|
| 55 |
+
def add_comment(
|
| 56 |
+
self,
|
| 57 |
+
review_id: str,
|
| 58 |
+
author: str,
|
| 59 |
+
comment: str,
|
| 60 |
+
category: str = "general"
|
| 61 |
+
) -> Dict[str, Any]:
|
| 62 |
+
"""Add a comment to a review."""
|
| 63 |
+
if review_id not in self.reviews:
|
| 64 |
+
return {"error": "Review not found"}
|
| 65 |
+
|
| 66 |
+
comment_obj = ReviewComment(
|
| 67 |
+
author=author,
|
| 68 |
+
comment=comment,
|
| 69 |
+
timestamp=time.time(),
|
| 70 |
+
category=category
|
| 71 |
+
)
|
| 72 |
+
self.reviews[review_id]["comments"].append(comment_obj)
|
| 73 |
+
return {"success": True, "comment": comment_obj}
|
| 74 |
+
|
| 75 |
+
def add_approval(
|
| 76 |
+
self,
|
| 77 |
+
review_id: str,
|
| 78 |
+
approver: str,
|
| 79 |
+
role: str,
|
| 80 |
+
approved: bool,
|
| 81 |
+
notes: Optional[str] = None
|
| 82 |
+
) -> Dict[str, Any]:
|
| 83 |
+
"""Add an approval from a stakeholder."""
|
| 84 |
+
if review_id not in self.reviews:
|
| 85 |
+
return {"error": "Review not found"}
|
| 86 |
+
|
| 87 |
+
approval = Approval(
|
| 88 |
+
approver=approver,
|
| 89 |
+
role=role,
|
| 90 |
+
approved=approved,
|
| 91 |
+
timestamp=time.time(),
|
| 92 |
+
notes=notes
|
| 93 |
+
)
|
| 94 |
+
self.reviews[review_id]["approvals"].append(approval)
|
| 95 |
+
|
| 96 |
+
# Update status if all stakeholders approved
|
| 97 |
+
review = self.reviews[review_id]
|
| 98 |
+
required_stakeholders = set(review["stakeholders"])
|
| 99 |
+
approved_by = {a.approver for a in review["approvals"] if a.approved}
|
| 100 |
+
|
| 101 |
+
if required_stakeholders.issubset(approved_by):
|
| 102 |
+
review["status"] = "approved"
|
| 103 |
+
elif any(not a.approved for a in review["approvals"]):
|
| 104 |
+
review["status"] = "blocked"
|
| 105 |
+
|
| 106 |
+
return {"success": True, "approval": approval, "review_status": review["status"]}
|
| 107 |
+
|
| 108 |
+
def get_review_summary(self, review_id: str) -> Dict[str, Any]:
|
| 109 |
+
"""Get summary of a review."""
|
| 110 |
+
if review_id not in self.reviews:
|
| 111 |
+
return {"error": "Review not found"}
|
| 112 |
+
|
| 113 |
+
review = self.reviews[review_id]
|
| 114 |
+
return {
|
| 115 |
+
"id": review_id,
|
| 116 |
+
"project_name": review["project_name"],
|
| 117 |
+
"status": review["status"],
|
| 118 |
+
"total_comments": len(review["comments"]),
|
| 119 |
+
"total_approvals": len(review["approvals"]),
|
| 120 |
+
"approved_by": [a.approver for a in review["approvals"] if a.approved],
|
| 121 |
+
"blocked_by": [a.approver for a in review["approvals"] if not a.approved],
|
| 122 |
+
"pending_approvals": [
|
| 123 |
+
s for s in review["stakeholders"]
|
| 124 |
+
if s not in [a.approver for a in review["approvals"]]
|
| 125 |
+
]
|
| 126 |
+
}
|
| 127 |
+
|