# Prometheus alerting rules for github-actions-runner-exporter. # Load with `rule_files:`, or paste the group into a PrometheusRule's spec.groups. # Thresholds are starting points; tune `for:` and the ratios to your runner fleet. groups: - name: github-actions-runner-exporter rules: - alert: GithubRunnerOffline expr: max by (runner, os) (github_runner_up) == 0 for: 10m labels: severity: warning annotations: summary: "Self-hosted runner {{ $labels.runner }} is offline" description: The runner is registered but not connected to GitHub. Jobs that need it will queue. - alert: GithubRunnersAllOffline expr: count(github_runner_up) > 0 and sum(github_runner_up) == 0 for: 5m labels: severity: critical annotations: summary: All self-hosted runners are offline description: No self-hosted runner can pick up jobs; every workflow that targets them is stuck. - alert: GithubRunnersSaturated # Every online runner busy for a long stretch: jobs are probably queueing. expr: sum(github_runner_busy) >= sum(github_runner_up) and sum(github_runner_up) > 0 for: 30m labels: severity: warning annotations: summary: All online self-hosted runners have been busy for 30 minutes description: New jobs are likely waiting in the queue. Consider adding runners. - alert: GithubRunnerExporterStale expr: max(github_runners_up) == 0 for: 5m labels: severity: warning annotations: summary: Runner status is stale description: The exporter's last runner poll failed and a cached result is being served. Check the token and GitHub API reachability. - alert: GithubOrgStatsStale expr: max(github_org_up) == 0 for: 30m labels: severity: warning annotations: summary: Org and repo stats are stale description: The org stats poll keeps failing; CI, PR and Dependabot metrics are no longer updating. - alert: GithubApiRateLimitLow expr: max(github_rate_limit_remaining) / max(github_rate_limit_limit) < 0.10 for: 10m labels: severity: warning annotations: summary: "GitHub API rate limit at {{ $value | humanizePercentage }} remaining" description: The exporter (or anything else sharing the token) is close to the limit, and polls will start failing. Raise the cache TTLs or use a separate token. - alert: GithubWorkflowFailing # The latest completed run of the workflow, on whatever branch ran last. expr: max by (repo, workflow, url, conclusion) (github_repo_ci_last_run_conclusion{conclusion=~"failure|timed_out"}) == 1 for: 1h labels: severity: info annotations: summary: "{{ $labels.repo }}: {{ $labels.workflow }} last run {{ $labels.conclusion }}" description: "Latest run: {{ $labels.url }}" - alert: GithubDependabotCriticalAlerts expr: sum by (repo) (github_repo_dependabot_alerts_open{severity="critical"}) > 0 for: 1h labels: severity: warning annotations: summary: "{{ $labels.repo }} has {{ $value }} open critical Dependabot alert(s)" description: A dependency has a known critical vulnerability with an available advisory.