CoolFace
Apppublic

OnyxMunk/AudioForge

sourceHugging Facemitupdated 8mo agoView on Hugging Face
0likes
generate_launch_report.py509 linesDownload Raw Back to scripts
1#!/usr/bin/env python3
2"""
3Generate comprehensive launch readiness report
4Combines all verification checks into a single PDF/HTML report
5"""
6
7import asyncio
8import json
9import subprocess
10import sys
11from datetime import datetime
12from pathlib import Path
13from typing import Dict, List, Any
14
15try:
16    from jinja2 import Template
17    import markdown
18except ImportError:
19    print("Installing required packages...")
20    subprocess.run([sys.executable, "-m", "pip", "install", "jinja2", "markdown"], check=True)
21    from jinja2 import Template
22    import markdown
23
24
25HTML_TEMPLATE = """
26<!DOCTYPE html>
27<html lang="en">
28<head>
29    <meta charset="UTF-8">
30    <meta name="viewport" content="width=device-width, initial-scale=1.0">
31    <title>AudioForge Launch Report - {{ timestamp }}</title>
32    <style>
33        * {
34            margin: 0;
35            padding: 0;
36            box-sizing: border-box;
37        }
38        
39        body {
40            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
41            line-height: 1.6;
42            color: #333;
43            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
44            padding: 20px;
45        }
46        
47        .container {
48            max-width: 1200px;
49            margin: 0 auto;
50            background: white;
51            border-radius: 12px;
52            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
53            overflow: hidden;
54        }
55        
56        .header {
57            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
58            color: white;
59            padding: 40px;
60            text-align: center;
61        }
62        
63        .header h1 {
64            font-size: 2.5em;
65            margin-bottom: 10px;
66            font-weight: 700;
67        }
68        
69        .header .subtitle {
70            font-size: 1.2em;
71            opacity: 0.9;
72        }
73        
74        .header .timestamp {
75            margin-top: 20px;
76            font-size: 0.9em;
77            opacity: 0.8;
78        }
79        
80        .summary {
81            padding: 40px;
82            background: #f8f9fa;
83            border-bottom: 2px solid #e9ecef;
84        }
85        
86        .summary-grid {
87            display: grid;
88            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
89            gap: 20px;
90            margin-top: 20px;
91        }
92        
93        .summary-card {
94            background: white;
95            padding: 20px;
96            border-radius: 8px;
97            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
98            text-align: center;
99            transition: transform 0.2s;
100        }
101        
102        .summary-card:hover {
103            transform: translateY(-5px);
104            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
105        }
106        
107        .summary-card .value {
108            font-size: 2.5em;
109            font-weight: 700;
110            margin: 10px 0;
111        }
112        
113        .summary-card .label {
114            color: #666;
115            font-size: 0.9em;
116            text-transform: uppercase;
117            letter-spacing: 1px;
118        }
119        
120        .summary-card.success .value { color: #28a745; }
121        .summary-card.warning .value { color: #ffc107; }
122        .summary-card.danger .value { color: #dc3545; }
123        .summary-card.info .value { color: #17a2b8; }
124        
125        .content {
126            padding: 40px;
127        }
128        
129        .section {
130            margin-bottom: 40px;
131        }
132        
133        .section-header {
134            display: flex;
135            align-items: center;
136            gap: 15px;
137            margin-bottom: 20px;
138            padding-bottom: 15px;
139            border-bottom: 2px solid #e9ecef;
140        }
141        
142        .section-header h2 {
143            font-size: 1.8em;
144            color: #667eea;
145        }
146        
147        .section-badge {
148            padding: 5px 15px;
149            border-radius: 20px;
150            font-size: 0.8em;
151            font-weight: 600;
152        }
153        
154        .section-badge.pass {
155            background: #d4edda;
156            color: #155724;
157        }
158        
159        .section-badge.fail {
160            background: #f8d7da;
161            color: #721c24;
162        }
163        
164        .section-badge.warn {
165            background: #fff3cd;
166            color: #856404;
167        }
168        
169        .checks-table {
170            width: 100%;
171            border-collapse: collapse;
172            margin-top: 20px;
173        }
174        
175        .checks-table th {
176            background: #f8f9fa;
177            padding: 12px;
178            text-align: left;
179            font-weight: 600;
180            border-bottom: 2px solid #dee2e6;
181        }
182        
183        .checks-table td {
184            padding: 12px;
185            border-bottom: 1px solid #e9ecef;
186        }
187        
188        .checks-table tr:hover {
189            background: #f8f9fa;
190        }
191        
192        .status-icon {
193            font-size: 1.5em;
194            display: inline-block;
195            width: 30px;
196            text-align: center;
197        }
198        
199        .check-details {
200            font-size: 0.9em;
201            color: #666;
202            margin-top: 5px;
203        }
204        
205        .fix-command {
206            background: #f8f9fa;
207            padding: 8px 12px;
208            border-radius: 4px;
209            font-family: 'Courier New', monospace;
210            font-size: 0.85em;
211            margin-top: 5px;
212            border-left: 3px solid #ffc107;
213        }
214        
215        .footer {
216            background: #f8f9fa;
217            padding: 30px;
218            text-align: center;
219            color: #666;
220            border-top: 2px solid #e9ecef;
221        }
222        
223        .footer .logo {
224            font-size: 2em;
225            margin-bottom: 10px;
226        }
227        
228        .progress-bar {
229            width: 100%;
230            height: 30px;
231            background: #e9ecef;
232            border-radius: 15px;
233            overflow: hidden;
234            margin: 20px 0;
235        }
236        
237        .progress-fill {
238            height: 100%;
239            background: linear-gradient(90deg, #28a745 0%, #20c997 100%);
240            display: flex;
241            align-items: center;
242            justify-content: center;
243            color: white;
244            font-weight: 600;
245            transition: width 0.3s ease;
246        }
247        
248        .action-items {
249            background: #fff3cd;
250            border-left: 4px solid #ffc107;
251            padding: 20px;
252            margin: 20px 0;
253            border-radius: 4px;
254        }
255        
256        .action-items h3 {
257            color: #856404;
258            margin-bottom: 15px;
259        }
260        
261        .action-items ul {
262            list-style: none;
263            padding-left: 0;
264        }
265        
266        .action-items li {
267            padding: 8px 0;
268            border-bottom: 1px solid #ffeaa7;
269        }
270        
271        .action-items li:last-child {
272            border-bottom: none;
273        }
274        
275        @media print {
276            body {
277                background: white;
278                padding: 0;
279            }
280            
281            .container {
282                box-shadow: none;
283            }
284            
285            .summary-card:hover {
286                transform: none;
287            }
288        }
289    </style>
290</head>
291<body>
292    <div class="container">
293        <div class="header">
294            <h1>๐ŸŽต AudioForge Launch Report</h1>
295            <div class="subtitle">Production Readiness Verification</div>
296            <div class="timestamp">Generated: {{ timestamp }}</div>
297        </div>
298        
299        <div class="summary">
300            <h2>Executive Summary</h2>
301            <div class="progress-bar">
302                <div class="progress-fill" style="width: {{ overall_success_rate }}%;">
303                    {{ overall_success_rate }}% Ready
304                </div>
305            </div>
306            
307            <div class="summary-grid">
308                <div class="summary-card success">
309                    <div class="label">Passed</div>
310                    <div class="value">{{ total_passed }}</div>
311                </div>
312                <div class="summary-card danger">
313                    <div class="label">Failed</div>
314                    <div class="value">{{ total_failed }}</div>
315                </div>
316                <div class="summary-card warning">
317                    <div class="label">Warnings</div>
318                    <div class="value">{{ total_warned }}</div>
319                </div>
320                <div class="summary-card info">
321                    <div class="label">Total Checks</div>
322                    <div class="value">{{ total_checks }}</div>
323                </div>
324            </div>
325            
326            {% if overall_success_rate == 100 %}
327            <div style="margin-top: 30px; padding: 20px; background: #d4edda; border-radius: 8px; text-align: center;">
328                <h3 style="color: #155724; font-size: 1.5em;">๐ŸŽ‰ READY TO LAUNCH!</h3>
329                <p style="color: #155724; margin-top: 10px;">All systems are go. You're cleared for production deployment.</p>
330            </div>
331            {% elif overall_success_rate >= 90 %}
332            <div style="margin-top: 30px; padding: 20px; background: #fff3cd; border-radius: 8px; text-align: center;">
333                <h3 style="color: #856404; font-size: 1.5em;">โš ๏ธ ALMOST READY</h3>
334                <p style="color: #856404; margin-top: 10px;">Minor issues to address before launch.</p>
335            </div>
336            {% else %}
337            <div style="margin-top: 30px; padding: 20px; background: #f8d7da; border-radius: 8px; text-align: center;">
338                <h3 style="color: #721c24; font-size: 1.5em;">โŒ NOT READY</h3>
339                <p style="color: #721c24; margin-top: 10px;">Critical issues must be resolved before launch.</p>
340            </div>
341            {% endif %}
342        </div>
343        
344        <div class="content">
345            {% for section_name, section_data in sections.items() %}
346            <div class="section">
347                <div class="section-header">
348                    <h2>{{ section_name }}</h2>
349                    {% if section_data.success_rate == 100 %}
350                    <span class="section-badge pass">โœ… {{ section_data.passed }}/{{ section_data.total }}</span>
351                    {% elif section_data.failed > 0 %}
352                    <span class="section-badge fail">โŒ {{ section_data.failed }} Failed</span>
353                    {% else %}
354                    <span class="section-badge warn">โš ๏ธ {{ section_data.warned }} Warnings</span>
355                    {% endif %}
356                </div>
357                
358                <table class="checks-table">
359                    <thead>
360                        <tr>
361                            <th style="width: 50px;">Status</th>
362                            <th>Check</th>
363                            <th>Message</th>
364                        </tr>
365                    </thead>
366                    <tbody>
367                        {% for check in section_data.checks %}
368                        <tr>
369                            <td><span class="status-icon">{{ check.status_icon }}</span></td>
370                            <td><strong>{{ check.name }}</strong></td>
371                            <td>
372                                {{ check.message }}
373                                {% if check.details %}
374                                <div class="check-details">{{ check.details }}</div>
375                                {% endif %}
376                                {% if check.fix_command %}
377                                <div class="fix-command">Fix: {{ check.fix_command }}</div>
378                                {% endif %}
379                            </td>
380                        </tr>
381                        {% endfor %}
382                    </tbody>
383                </table>
384            </div>
385            {% endfor %}
386            
387            {% if action_items %}
388            <div class="action-items">
389                <h3>โšก Action Items</h3>
390                <ul>
391                    {% for item in action_items %}
392                    <li>{{ item }}</li>
393                    {% endfor %}
394                </ul>
395            </div>
396            {% endif %}
397        </div>
398        
399        <div class="footer">
400            <div class="logo">๐Ÿผโšก</div>
401            <p>AudioForge Launch Verification System</p>
402            <p style="margin-top: 10px; font-size: 0.9em;">
403                Forged by FusionPanda | {{ timestamp }}
404            </p>
405        </div>
406    </div>
407</body>
408</html>
409"""
410
411
412async def generate_report():
413    """Generate comprehensive launch report."""
414    print("๐ŸŽต Generating AudioForge Launch Report...")
415    print("=" * 60)
416    
417    # Run verification script
418    print("\n๐Ÿ“Š Running verification checks...")
419    result = subprocess.run(
420        [sys.executable, "scripts/launch_verification.py", "--json", "launch-results.json"],
421        capture_output=True,
422        text=True
423    )
424    
425    # Load results
426    results_file = Path("launch-results.json")
427    if not results_file.exists():
428        print("โŒ Verification results not found!")
429        sys.exit(1)
430    
431    with open(results_file) as f:
432        data = json.load(f)
433    
434    # Calculate totals
435    total_passed = sum(section["passed"] for section in data.values())
436    total_failed = sum(section["failed"] for section in data.values())
437    total_warned = sum(section["warned"] for section in data.values())
438    total_checks = sum(section["total"] for section in data.values())
439    overall_success_rate = round((total_passed / total_checks * 100) if total_checks > 0 else 0, 1)
440    
441    # Collect action items
442    action_items = []
443    for section_name, section_data in data.items():
444        for check in section_data["checks"]:
445            if check.get("details") and ("fix" in check["details"].lower() or "missing" in check["details"].lower()):
446                action_items.append(f"{section_name}: {check['name']} - {check['message']}")
447    
448    # Prepare template data
449    template_data = {
450        "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
451        "total_passed": total_passed,
452        "total_failed": total_failed,
453        "total_warned": total_warned,
454        "total_checks": total_checks,
455        "overall_success_rate": overall_success_rate,
456        "sections": data,
457        "action_items": action_items[:10],  # Top 10 action items
458    }
459    
460    # Add status icons
461    status_icons = {
462        "PASS": "โœ…",
463        "FAIL": "โŒ",
464        "WARN": "โš ๏ธ",
465        "SKIP": "โญ๏ธ",
466        "INFO": "โ„น๏ธ",
467    }
468    
469    for section_data in template_data["sections"].values():
470        for check in section_data["checks"]:
471            check["status_icon"] = status_icons.get(check["status"], "โ“")
472    
473    # Generate HTML report
474    template = Template(HTML_TEMPLATE)
475    html_content = template.render(**template_data)
476    
477    # Save report
478    report_path = Path("LAUNCH_REPORT.html")
479    report_path.write_text(html_content, encoding="utf-8")
480    
481    print(f"\nโœ… Report generated: {report_path.absolute()}")
482    print(f"๐Ÿ“Š Overall Success Rate: {overall_success_rate}%")
483    print(f"โœ… Passed: {total_passed}")
484    print(f"โŒ Failed: {total_failed}")
485    print(f"โš ๏ธ  Warnings: {total_warned}")
486    
487    # Print status
488    if overall_success_rate == 100:
489        print("\n๐ŸŽ‰ READY TO LAUNCH!")
490    elif overall_success_rate >= 90:
491        print("\nโš ๏ธ  ALMOST READY - Minor issues to fix")
492    else:
493        print("\nโŒ NOT READY - Critical issues found")
494    
495    # Open report in browser (optional)
496    try:
497        import webbrowser
498        webbrowser.open(f"file://{report_path.absolute()}")
499        print(f"\n๐ŸŒ Opening report in browser...")
500    except Exception:
501        pass
502    
503    return overall_success_rate >= 90
504
505
506if __name__ == "__main__":
507    success = asyncio.run(generate_report())
508    sys.exit(0 if success else 1)
509