|
|
"""Export utilities for reports in multiple formats.""" |
|
|
|
|
|
from __future__ import annotations |
|
|
|
|
|
import json |
|
|
from datetime import datetime |
|
|
from typing import Any, Dict, Optional |
|
|
|
|
|
|
|
|
def export_json(data: Dict[str, Any], filename: Optional[str] = None) -> str: |
|
|
"""Export data as JSON.""" |
|
|
output = json.dumps(data, indent=2, default=str) |
|
|
if filename: |
|
|
with open(filename, 'w') as f: |
|
|
f.write(output) |
|
|
return output |
|
|
|
|
|
|
|
|
def export_markdown(data: Dict[str, Any], filename: Optional[str] = None) -> str: |
|
|
"""Export readiness report as Markdown.""" |
|
|
md_lines = [ |
|
|
f"# Deployment Readiness Report", |
|
|
f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", |
|
|
"", |
|
|
"## Summary", |
|
|
"" |
|
|
] |
|
|
|
|
|
|
|
|
if "plan" in data: |
|
|
plan = data["plan"] |
|
|
md_lines.extend([ |
|
|
f"### Deployment Plan", |
|
|
plan.get("summary", "No summary available"), |
|
|
"", |
|
|
"#### Checklist Items:", |
|
|
"" |
|
|
]) |
|
|
for item in plan.get("items", [])[:10]: |
|
|
status_icon = "β
" if item.get("status") == "done" else "β³" |
|
|
md_lines.append(f"- {status_icon} **{item.get('title', 'Untitled')}**") |
|
|
md_lines.append(f" - Category: {item.get('category', 'general')}") |
|
|
md_lines.append(f" - {item.get('description', '')}") |
|
|
md_lines.append("") |
|
|
|
|
|
|
|
|
if "review" in data: |
|
|
review = data["review"] |
|
|
decision = review.get("decision", "unknown") |
|
|
confidence = review.get("confidence", 0.0) |
|
|
md_lines.extend([ |
|
|
"## Review Decision", |
|
|
f"**Decision**: {decision.upper()}", |
|
|
f"**Confidence**: {confidence:.1%}", |
|
|
"", |
|
|
"### Findings:", |
|
|
"" |
|
|
]) |
|
|
for finding in review.get("findings", [])[:5]: |
|
|
severity = finding.get("severity", "medium") |
|
|
severity_icon = "π΄" if severity == "high" else "π‘" if severity == "medium" else "π’" |
|
|
md_lines.append(f"- {severity_icon} **{severity.upper()}**: {finding.get('note', '')}") |
|
|
md_lines.append("") |
|
|
|
|
|
|
|
|
if "docs_references" in data and data["docs_references"]: |
|
|
docs_refs = data["docs_references"] |
|
|
md_lines.extend([ |
|
|
"## Documentation References", |
|
|
f"**Framework**: {docs_refs.get('framework', 'Unknown')}", |
|
|
f"**Platform**: {docs_refs.get('platform', 'Unknown')}", |
|
|
"", |
|
|
"### Lookups:", |
|
|
"" |
|
|
]) |
|
|
for lookup in docs_refs.get("lookups", [])[:5]: |
|
|
lookup_type = lookup.get("type", "unknown") |
|
|
status = lookup.get("status", "unknown") |
|
|
md_lines.append(f"- **{lookup_type}**: {status}") |
|
|
md_lines.append("") |
|
|
|
|
|
|
|
|
if "deployment" in data and data["deployment"]: |
|
|
deploy = data["deployment"] |
|
|
md_lines.extend([ |
|
|
"## Deployment Actions", |
|
|
f"**Repository**: {deploy.get('repo', 'Not configured')}", |
|
|
f"**Branch**: {deploy.get('branch', 'main')}", |
|
|
f"**Ready**: {'β
' if deploy.get('ready') else 'β'}", |
|
|
"", |
|
|
"### Actions:", |
|
|
"" |
|
|
]) |
|
|
for action in deploy.get("actions", [])[:5]: |
|
|
action_type = action.get("type", "unknown") |
|
|
message = action.get("message", action.get("title", "")) |
|
|
md_lines.append(f"- **{action_type}**: {message}") |
|
|
md_lines.append("") |
|
|
|
|
|
|
|
|
sponsor_data = data.get("sponsor_synthesis") |
|
|
if sponsor_data: |
|
|
md_lines.extend([ |
|
|
"## Sponsor LLM Cross-Checks", |
|
|
"", |
|
|
]) |
|
|
for key, value in sponsor_data.items(): |
|
|
md_lines.append(f"### {key.replace('_', ' ').title()}") |
|
|
md_lines.append(str(value)) |
|
|
md_lines.append("") |
|
|
|
|
|
output = "\n".join(md_lines) |
|
|
if filename: |
|
|
with open(filename, 'w') as f: |
|
|
f.write(output) |
|
|
return output |
|
|
|
|
|
|
|
|
def export_pdf(data: Dict[str, Any], filename: Optional[str] = None) -> bytes: |
|
|
"""Export as PDF (requires markdown2pdf or similar).""" |
|
|
|
|
|
|
|
|
md_content = export_markdown(data) |
|
|
|
|
|
return md_content.encode('utf-8') |
|
|
|
|
|
|