name: CI/CD Metrics Dashboard
on:
workflow_run:
workflows: ["CI/CD Pipeline", "Optimized CI/CD Pipeline"]
types: [completed]
schedule:
- cron: '0 0 * * *' # Daily at midnight
workflow_dispatch:
jobs:
collect-metrics:
name: Collect CI/CD Metrics
runs-on: ubuntu-latest
permissions:
contents: write
actions: read
checks: read
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Collect workflow metrics
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python - << 'EOF'
import json
import os
import subprocess
from datetime import datetime, timedelta
from collections import defaultdict
# Get workflow runs from last 7 days
since = (datetime.now() - timedelta(days=7)).isoformat()
cmd = [
"gh", "api",
f"/repos/${{github.repository}}/actions/runs",
"--paginate",
"-q", f".workflow_runs[] | select(.created_at > \"{since}\")"
]
result = subprocess.run(cmd, capture_output=True, text=True)
runs = []
for line in result.stdout.strip().split('\n'):
if line:
runs.append(json.loads(line))
# Calculate metrics
metrics = {
"total_runs": len(runs),
"success_rate": 0,
"average_duration_minutes": 0,
"workflows": defaultdict(lambda: {"total": 0, "success": 0, "failed": 0})
}
successful_runs = 0
total_duration = 0
for run in runs:
workflow_name = run.get("name", "Unknown")
conclusion = run.get("conclusion", "")
metrics["workflows"][workflow_name]["total"] += 1
if conclusion == "success":
successful_runs += 1
metrics["workflows"][workflow_name]["success"] += 1
elif conclusion == "failure":
metrics["workflows"][workflow_name]["failed"] += 1
# Calculate duration
if run.get("created_at") and run.get("updated_at"):
start = datetime.fromisoformat(run["created_at"].replace("Z", "+00:00"))
end = datetime.fromisoformat(run["updated_at"].replace("Z", "+00:00"))
duration = (end - start).total_seconds() / 60
total_duration += duration
if runs:
metrics["success_rate"] = (successful_runs / len(runs)) * 100
metrics["average_duration_minutes"] = total_duration / len(runs)
# Save metrics
with open("metrics.json", "w") as f:
json.dump(metrics, f, indent=2, default=str)
print(f"Total runs: {metrics['total_runs']}")
print(f"Success rate: {metrics['success_rate']:.1f}%")
print(f"Average duration: {metrics['average_duration_minutes']:.1f} minutes")
EOF
- name: Generate dashboard
run: |
cat > dashboard.md << 'EOF'
# CI/CD Metrics Dashboard
> Last updated: $(date)
## 📊 7-Day Overview
EOF
python - << 'PYTHON'
import json
with open("metrics.json") as f:
metrics = json.load(f)
with open("dashboard.md", "a") as f:
f.write(f"- **Total Pipeline Runs**: {metrics['total_runs']}\n")
f.write(f"- **Success Rate**: {metrics['success_rate']:.1f}%\n")
f.write(f"- **Average Duration**: {metrics['average_duration_minutes']:.1f} minutes\n\n")
f.write("## 📈 Workflow Breakdown\n\n")
f.write("| Workflow | Total | Success | Failed | Success Rate |\n")
f.write("|----------|-------|---------|--------|-------------|\n")
for name, stats in metrics['workflows'].items():
success_rate = (stats['success'] / stats['total'] * 100) if stats['total'] > 0 else 0
emoji = "✅" if success_rate >= 95 else "⚠️" if success_rate >= 80 else "❌"
f.write(f"| {name} | {stats['total']} | {stats['success']} | {stats['failed']} | {emoji} {success_rate:.1f}% |\n")
f.write("\n## 🎯 Health Score\n\n")
overall_health = metrics['success_rate']
if overall_health >= 95:
f.write("### 🟢 EXCELLENT ({:.1f}%)\n".format(overall_health))
f.write("Pipeline is operating at peak efficiency.\n")
elif overall_health >= 85:
f.write("### 🟡 GOOD ({:.1f}%)\n".format(overall_health))
f.write("Pipeline is healthy with minor issues.\n")
elif overall_health >= 75:
f.write("### 🟠 FAIR ({:.1f}%)\n".format(overall_health))
f.write("Pipeline needs attention.\n")
else:
f.write("### 🔴 POOR ({:.1f}%)\n".format(overall_health))
f.write("Pipeline requires immediate attention.\n")
PYTHON
- name: Upload metrics artifact
uses: actions/upload-artifact@v4
with:
name: ci-metrics-${{ github.run_id }}
path: |
metrics.json
dashboard.md
retention-days: 30
- name: Update metrics branch
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
# Create or checkout metrics branch
git checkout -B metrics || git checkout metrics
# Copy metrics files
mkdir -p .metrics
cp metrics.json .metrics/
cp dashboard.md .metrics/README.md
# Commit and push
git add .metrics/
git commit -m "Update CI/CD metrics - $(date)" || echo "No changes to commit"
git push origin metrics --force