First Init
Deploy to Production / Build & Verify (push) Failing after 5m56s
Ping Search Engines / Notify Search Engines (push) Successful in 2s
Deploy to Production / Pre-Deploy Tests (push) Has been skipped
Deploy to Production / Deploy to Railway (push) Has been skipped
Deploy to Production / Deploy to Render (push) Has been skipped
Deploy to Production / Deploy to VPS (PM2) (push) Has been skipped
Deploy to Production / Deploy to Fly.io (push) Has been skipped
Deploy to Production / Post-Deploy Verification (push) Has been skipped
Deploy to Production / Notify on Failure (push) Successful in 2s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Smoke Tests (P0) (push) Failing after 11m26s
E2E Test Suite / Form Interaction Tests (push) Failing after 11m42s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 12m2s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 16m14s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 17m45s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 25m23s
E2E Test Suite / Security Header Tests (push) Failing after 7m55s
E2E Test Suite / Test Report Summary (push) Failing after 20s
E2E Test Suite / Mobile Device Tests (push) Failing after 2h49m9s
Uptime Monitor / Health & Response Time (push) Failing after 2s
Uptime Monitor / SSL Certificate (push) Successful in 2s
Uptime Monitor / Send Alerts (push) Failing after 3s
Uptime Monitor / Record Uptime Success (push) Has been skipped
Deploy to Production / Build & Verify (push) Failing after 5m56s
Ping Search Engines / Notify Search Engines (push) Successful in 2s
Deploy to Production / Pre-Deploy Tests (push) Has been skipped
Deploy to Production / Deploy to Railway (push) Has been skipped
Deploy to Production / Deploy to Render (push) Has been skipped
Deploy to Production / Deploy to VPS (PM2) (push) Has been skipped
Deploy to Production / Deploy to Fly.io (push) Has been skipped
Deploy to Production / Post-Deploy Verification (push) Has been skipped
Deploy to Production / Notify on Failure (push) Successful in 2s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Smoke Tests (P0) (push) Failing after 11m26s
E2E Test Suite / Form Interaction Tests (push) Failing after 11m42s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 12m2s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 16m14s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 17m45s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 25m23s
E2E Test Suite / Security Header Tests (push) Failing after 7m55s
E2E Test Suite / Test Report Summary (push) Failing after 20s
E2E Test Suite / Mobile Device Tests (push) Failing after 2h49m9s
Uptime Monitor / Health & Response Time (push) Failing after 2s
Uptime Monitor / SSL Certificate (push) Successful in 2s
Uptime Monitor / Send Alerts (push) Failing after 3s
Uptime Monitor / Record Uptime Success (push) Has been skipped
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Lighthouse Performance Audit Script
|
||||
Runs Lighthouse audits on specified URLs and reports results
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def run_lighthouse(url, output_file=None):
|
||||
"""Run Lighthouse audit on a URL"""
|
||||
cmd = [
|
||||
'npx', 'lighthouse', url,
|
||||
'--output=json',
|
||||
'--output-path=stdout',
|
||||
'--chrome-flags="--headless --no-sandbox"',
|
||||
'--quiet'
|
||||
]
|
||||
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
|
||||
if result.returncode != 0:
|
||||
print(f"Error running Lighthouse on {url}: {result.stderr}")
|
||||
return None
|
||||
|
||||
data = json.loads(result.stdout)
|
||||
return data
|
||||
except subprocess.TimeoutExpired:
|
||||
print(f"Timeout running Lighthouse on {url}")
|
||||
return None
|
||||
except json.JSONDecodeError:
|
||||
print(f"Failed to parse Lighthouse output for {url}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Unexpected error for {url}: {e}")
|
||||
return None
|
||||
|
||||
def extract_scores(lighthouse_data):
|
||||
"""Extract key scores from Lighthouse data"""
|
||||
if not lighthouse_data or 'categories' not in lighthouse_data:
|
||||
return None
|
||||
|
||||
categories = lighthouse_data['categories']
|
||||
return {
|
||||
'performance': int(categories.get('performance', {}).get('score', 0) * 100),
|
||||
'accessibility': int(categories.get('accessibility', {}).get('score', 0) * 100),
|
||||
'best-practices': int(categories.get('best-practices', {}).get('score', 0) * 100),
|
||||
'seo': int(categories.get('seo', {}).get('score', 0) * 100),
|
||||
}
|
||||
|
||||
def get_issues(lighthouse_data):
|
||||
"""Extract issues from Lighthouse audit"""
|
||||
if not lighthouse_data or 'audits' not in lighthouse_data:
|
||||
return []
|
||||
|
||||
issues = []
|
||||
audits = lighthouse_data['audits']
|
||||
|
||||
# Key audits to check
|
||||
important_audits = [
|
||||
'first-contentful-paint',
|
||||
'largest-contentful-paint',
|
||||
'cumulative-layout-shift',
|
||||
'total-blocking-time',
|
||||
'speed-index',
|
||||
'interactive',
|
||||
'image-alt',
|
||||
'document-title',
|
||||
'meta-description',
|
||||
'link-text',
|
||||
'crawlable-anchors',
|
||||
'color-contrast',
|
||||
'tap-targets',
|
||||
'viewport',
|
||||
'uses-responsive-images',
|
||||
'modern-image-formats',
|
||||
'offscreen-images',
|
||||
'render-blocking-resources',
|
||||
'unminified-css',
|
||||
'unminified-javascript',
|
||||
'unused-css-rules',
|
||||
'unused-javascript',
|
||||
]
|
||||
|
||||
for audit_id in important_audits:
|
||||
if audit_id in audits:
|
||||
audit = audits[audit_id]
|
||||
if audit.get('score') is not None and audit['score'] < 0.9:
|
||||
issues.append({
|
||||
'id': audit_id,
|
||||
'title': audit.get('title', audit_id),
|
||||
'score': audit.get('score'),
|
||||
'displayValue': audit.get('displayValue', ''),
|
||||
'description': audit.get('description', ''),
|
||||
})
|
||||
|
||||
return issues
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python lighthouse_audit.py <url>")
|
||||
sys.exit(1)
|
||||
|
||||
url = sys.argv[1]
|
||||
print(f"\n🔍 Running Lighthouse audit on: {url}\n")
|
||||
|
||||
data = run_lighthouse(url)
|
||||
if not data:
|
||||
print("❌ Failed to run Lighthouse audit")
|
||||
sys.exit(1)
|
||||
|
||||
scores = extract_scores(data)
|
||||
if not scores:
|
||||
print("❌ Failed to extract scores")
|
||||
sys.exit(1)
|
||||
|
||||
# Print results
|
||||
print("=" * 60)
|
||||
print("LIGHTHOUSE SCORES")
|
||||
print("=" * 60)
|
||||
|
||||
for category, score in scores.items():
|
||||
emoji = "✅" if score >= 90 else "⚠️" if score >= 50 else "❌"
|
||||
print(f"{emoji} {category.upper():20s}: {score:3d}/100")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("ISSUES FOUND")
|
||||
print("=" * 60 + "\n")
|
||||
|
||||
issues = get_issues(data)
|
||||
if issues:
|
||||
for issue in issues[:10]: # Show top 10 issues
|
||||
score_str = f"{int(issue['score'] * 100)}/100" if issue['score'] is not None else "N/A"
|
||||
print(f"⚠️ {issue['title']}")
|
||||
print(f" Score: {score_str}")
|
||||
if issue['displayValue']:
|
||||
print(f" Value: {issue['displayValue']}")
|
||||
print()
|
||||
else:
|
||||
print("✅ No major issues found!\n")
|
||||
|
||||
# Check if all scores >= 90
|
||||
all_passed = all(score >= 90 for score in scores.values())
|
||||
if all_passed:
|
||||
print("🎉 All scores are 90+! Great job!\n")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("⚠️ Some scores are below 90. Review issues above.\n")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user