diff --git a/.github/workflows/ci-monitor.yml b/.github/workflows/ci-monitor.yml index fa161017e..cf75771b5 100644 --- a/.github/workflows/ci-monitor.yml +++ b/.github/workflows/ci-monitor.yml @@ -2,7 +2,7 @@ name: CI Monitor on: schedule: - - cron: '0 */12 * * *' # Every 12 hours for main analysis + - cron: '0 */12 * * *' # Every 12 hours for main analysis workflow_dispatch: inputs: limit: @@ -65,6 +65,7 @@ jobs: retention-days: 30 ci-monitor-balance: + needs: ci-monitor if: github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request' runs-on: ubuntu-latest steps: diff --git a/scripts/ci_monitor/ci_analyzer.py b/scripts/ci_monitor/ci_analyzer.py index 47231f50f..ddd084e04 100755 --- a/scripts/ci_monitor/ci_analyzer.py +++ b/scripts/ci_monitor/ci_analyzer.py @@ -382,15 +382,13 @@ class SGLangCIAnalyzer: try: github_step_summary = os.environ.get("GITHUB_STEP_SUMMARY") if not github_step_summary: - print("â„šī¸ Not running in GitHub Actions, skipping summary generation") + print("Not running in GitHub Actions, skipping summary generation") return - print("📊 Generating GitHub Actions summary for CI Analysis...") + print("Generating GitHub Actions summary for CI Analysis...") summary_lines = [] - summary_lines.append( - "# 🔍 SGLang CI Analysis Report (Target Workflows Only)" - ) + summary_lines.append("# SGLang CI Analysis Report (Target Workflows Only)") summary_lines.append("") total = stats["total_runs"] @@ -400,26 +398,24 @@ class SGLangCIAnalyzer: skipped = stats["skipped_runs"] success_rate = (success / total * 100) if total > 0 else 0 - summary_lines.append("## 📊 Overall Statistics") + summary_lines.append("## Overall Statistics") summary_lines.append("") summary_lines.append("| Metric | Count | Percentage |") summary_lines.append("|--------|-------|------------|") summary_lines.append(f"| Total Runs | {total} | 100% |") summary_lines.append( - f"| ✅ Successful | {success} | {success/total*100:.1f}% |" + f"| Successful | {success} | {success/total*100:.1f}% |" ) - summary_lines.append(f"| ❌ Failed | {failed} | {failed/total*100:.1f}% |") + summary_lines.append(f"| Failed | {failed} | {failed/total*100:.1f}% |") summary_lines.append( - f"| đŸšĢ Cancelled | {cancelled} | {cancelled/total*100:.1f}% |" - ) - summary_lines.append( - f"| â­ī¸ Skipped | {skipped} | {skipped/total*100:.1f}% |" + f"| Cancelled | {cancelled} | {cancelled/total*100:.1f}% |" ) + summary_lines.append(f"| Skipped | {skipped} | {skipped/total*100:.1f}% |") summary_lines.append(f"| **Success Rate** | **{success_rate:.1f}%** | - |") summary_lines.append("") if stats["category_failures"]: - summary_lines.append("## 📁 Category Failure Statistics") + summary_lines.append("## Category Failure Statistics") summary_lines.append("") summary_lines.append("| Category | Failures |") summary_lines.append("|----------|----------|") @@ -430,7 +426,7 @@ class SGLangCIAnalyzer: summary_lines.append("") if stats["job_failures"]: - summary_lines.append("## 🔴 Most Frequently Failed Jobs (Top 20)") + summary_lines.append("## Most Frequently Failed Jobs (Top 20)") summary_lines.append("") top_failures = sorted( @@ -457,7 +453,7 @@ class SGLangCIAnalyzer: pr_text = f" by {pr_info['author']}" summary_lines.append( - f"✅ **Last Success:** [Run #{last_success['run_number']}]({last_success['url']}) ({success_date.strftime('%Y-%m-%d %H:%M')}){pr_text}" + f"**Last Success:** [Run #{last_success['run_number']}]({last_success['url']}) ({success_date.strftime('%Y-%m-%d %H:%M')}){pr_text}" ) summary_lines.append("") @@ -465,7 +461,7 @@ class SGLangCIAnalyzer: job in stats["job_failure_links"] and stats["job_failure_links"][job] ): - summary_lines.append("❌ **Recent Failures:**") + summary_lines.append("**Recent Failures:**") for link_info in stats["job_failure_links"][job]: created_at = datetime.fromisoformat( link_info["created_at"].replace("Z", "+00:00") @@ -484,7 +480,7 @@ class SGLangCIAnalyzer: summary_lines.append("") if stats["failure_patterns"]: - summary_lines.append("## đŸ”Ŧ Failure Pattern Analysis") + summary_lines.append("## Failure Pattern Analysis") summary_lines.append("") summary_lines.append("| Pattern | Count |") summary_lines.append("|---------|-------|") @@ -498,10 +494,10 @@ class SGLangCIAnalyzer: f.write("\n".join(summary_lines)) f.write("\n\n---\n\n") - print("✅ GitHub Actions summary generated successfully") + print("GitHub Actions summary generated successfully") except Exception as e: - print(f"❌ Failed to generate GitHub Actions summary: {e}") + print(f"Failed to generate GitHub Actions summary: {e}") def main(): diff --git a/scripts/ci_monitor/ci_analyzer_perf.py b/scripts/ci_monitor/ci_analyzer_perf.py index f5b345673..deb00a08a 100755 --- a/scripts/ci_monitor/ci_analyzer_perf.py +++ b/scripts/ci_monitor/ci_analyzer_perf.py @@ -612,18 +612,23 @@ class SGLangPerfAnalyzer: total_runs = len(runs) for i, run in enumerate(runs, 1): - print(f"Processing run {i}/{total_runs}: #{run.get('run_number')}") + if not isinstance(run, dict): + print(f" Warning: run #{i} is not a dict, skipping.") + continue run_info = { "run_number": run.get("run_number"), "created_at": run.get("created_at"), - "head_sha": run.get("head_sha", "")[:8], - "author": run.get("head_commit", {}) - .get("author", {}) - .get("name", "Unknown"), + "head_sha": (run.get("head_sha") or "")[:8], + "author": "Unknown", "pr_number": None, "url": f"https://github.com/{self.repo}/actions/runs/{run.get('id')}", } + head_commit = run.get("head_commit", {}) + if isinstance(head_commit, dict): + run_info["author"] = head_commit.get("author", {}).get( + "name", "Unknown" + ) # Extract PR number pull_requests = run.get("pull_requests", [])