#!/usr/bin/env bash # ============================================================================ # BLACKROAD OS, INC. - PROPRIETARY AND CONFIDENTIAL # BlackRoad GitHub Actions Monitor # Real-time CI/CD pipeline and workflow monitoring # ============================================================================ set -e # Color functions (printf-based, escape-safe) c_pink() { printf '\033[38;5;205m'; } c_blue() { printf '\033[38;5;75m'; } c_green() { printf '\033[38;5;82m'; } c_yellow() { printf '\033[38;5;226m'; } c_red() { printf '\033[38;5;196m'; } c_purple() { printf '\033[38;5;141m'; } c_orange() { printf '\033[38;5;208m'; } c_gray() { printf '\033[38;5;240m'; } c_cyan() { printf '\033[38;5;87m'; } c_white() { printf '\033[38;5;255m'; } c_reset() { printf '\033[0m'; } c_clear() { printf '\033[2J\033[H'; } c_bold() { printf '\033[1m'; } # GitHub organizations to monitor GITHUB_ORGS=( "BlackRoad-OS" "BlackRoad-AI" "BlackRoad-Labs" ) # ================== # DATA COLLECTORS # ================== check_gh_cli() { if ! command -v gh >/dev/null 2>&1; then return 1 fi return 0 } get_workflow_runs() { local org="$1" local limit="${2:-5}" if check_gh_cli; then # Get recent workflow runs across org gh run list --limit "$limit" --json status,conclusion,name,createdAt,event 2>/dev/null || echo "" else echo "" fi } get_repo_count() { local org="$1" if check_gh_cli; then gh repo list "$org" --limit 1000 --json name 2>/dev/null | jq '. | length' 2>/dev/null || echo "0" else echo "0" fi } get_workflow_count() { local org="$1" # Estimate based on repos (most repos have 1-3 workflows) local repos=$(get_repo_count "$org") echo $((repos * 2)) } # ================== # MOCK DATA (for demo when gh CLI unavailable) # ================== generate_mock_runs() { cat <<'EOF' [ { "name": "CI/CD Pipeline", "status": "completed", "conclusion": "success", "event": "push", "createdAt": "2026-02-16T03:45:00Z" }, { "name": "Deploy Production", "status": "completed", "conclusion": "success", "event": "push", "createdAt": "2026-02-16T03:30:00Z" }, { "name": "Run Tests", "status": "in_progress", "conclusion": null, "event": "pull_request", "createdAt": "2026-02-16T03:55:00Z" }, { "name": "Lint Code", "status": "completed", "conclusion": "failure", "event": "push", "createdAt": "2026-02-16T03:20:00Z" }, { "name": "Build Docker", "status": "completed", "conclusion": "success", "event": "push", "createdAt": "2026-02-16T03:10:00Z" } ] EOF } # ================== # DISPLAY COMPONENTS # ================== draw_header() { c_clear c_orange; c_bold printf "╔════════════════════════════════════════════════════════════════════════════════╗\n" printf "║ ║\n" printf "║ BLACKROAD OS - GITHUB ACTIONS MONITOR ║\n" printf "║ ║\n" printf "╚════════════════════════════════════════════════════════════════════════════════╝\n" c_reset printf "\n" } draw_org_summary() { c_cyan; c_bold printf "╔════════════════════════════════════════════════════════════════════════════════╗\n" printf "║ 📦 ORGANIZATION SUMMARY ║\n" printf "╚════════════════════════════════════════════════════════════════════════════════╝\n" c_reset printf "\n" local total_repos=0 local total_workflows=0 for org in "${GITHUB_ORGS[@]}"; do local repos=$(get_repo_count "$org") local workflows=$(get_workflow_count "$org") total_repos=$((total_repos + repos)) total_workflows=$((total_workflows + workflows)) printf " " c_blue; c_bold; printf "%-20s" "$org"; c_reset printf " " c_gray; printf "Repos: "; c_reset c_cyan; printf "%-5s" "$repos"; c_reset printf " " c_gray; printf "Workflows: "; c_reset c_purple; printf "%-5s" "$workflows"; c_reset printf "\n" done printf "\n" printf " " c_purple; printf "Total Repositories: "; c_reset c_cyan; c_bold; printf "%s\n" "$total_repos"; c_reset printf " " c_purple; printf "Total Workflows: "; c_reset c_purple; c_bold; printf "%s\n" "$total_workflows"; c_reset printf "\n" } draw_recent_runs() { local runs_json="$1" c_green; c_bold printf "╔════════════════════════════════════════════════════════════════════════════════╗\n" printf "║ 🔄 RECENT WORKFLOW RUNS ║\n" printf "╚════════════════════════════════════════════════════════════════════════════════╝\n" c_reset printf "\n" # Header printf " " c_gray printf "%-35s %-15s %-12s %-10s\n" "Workflow" "Status" "Event" "Time" c_reset printf " " c_gray printf "─────────────────────────────────────────────────────────────────────────────\n" c_reset # Parse and display runs if command -v jq >/dev/null 2>&1 && [[ -n "$runs_json" ]]; then echo "$runs_json" | jq -r '.[] | "\(.name)|\(.status)|\(.conclusion // "none")|\(.event)|\(.createdAt)"' 2>/dev/null | while IFS='|' read -r name status conclusion event created; do printf " " # Status indicator if [[ "$status" == "completed" ]]; then if [[ "$conclusion" == "success" ]]; then c_green; printf "✓"; c_reset elif [[ "$conclusion" == "failure" ]]; then c_red; printf "✗"; c_reset else c_gray; printf "○"; c_reset fi elif [[ "$status" == "in_progress" ]]; then c_yellow; printf "●"; c_reset else c_gray; printf "○"; c_reset fi printf " " # Workflow name (truncate) c_cyan printf "%-34s" "${name:0:34}" c_reset printf " " # Status case "$status" in completed) if [[ "$conclusion" == "success" ]]; then c_green; printf "%-15s" "Passed"; c_reset elif [[ "$conclusion" == "failure" ]]; then c_red; printf "%-15s" "Failed"; c_reset else c_gray; printf "%-15s" "$conclusion"; c_reset fi ;; in_progress) c_yellow; printf "%-15s" "Running"; c_reset ;; queued) c_cyan; printf "%-15s" "Queued"; c_reset ;; *) c_gray; printf "%-15s" "$status"; c_reset ;; esac printf " " # Event type c_purple printf "%-12s" "$event" c_reset printf " " # Time ago local now=$(date +%s) local created_ts=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$created" +%s 2>/dev/null || echo "$now") local diff=$((now - created_ts)) local time_ago if (( diff < 60 )); then time_ago="${diff}s ago" elif (( diff < 3600 )); then time_ago="$((diff / 60))m ago" elif (( diff < 86400 )); then time_ago="$((diff / 3600))h ago" else time_ago="$((diff / 86400))d ago" fi c_gray printf "%s" "$time_ago" c_reset printf "\n" done else printf " " c_gray; printf "No workflow data available\n"; c_reset fi printf "\n" } draw_workflow_stats() { local runs_json="$1" c_blue; c_bold printf "╔════════════════════════════════════════════════════════════════════════════════╗\n" printf "║ 📊 WORKFLOW STATISTICS ║\n" printf "╚════════════════════════════════════════════════════════════════════════════════╝\n" c_reset printf "\n" # Calculate stats from runs local total=0 local success=0 local failure=0 local running=0 if command -v jq >/dev/null 2>&1 && [[ -n "$runs_json" ]]; then total=$(echo "$runs_json" | jq '. | length' 2>/dev/null || echo "0") success=$(echo "$runs_json" | jq '[.[] | select(.conclusion == "success")] | length' 2>/dev/null || echo "0") failure=$(echo "$runs_json" | jq '[.[] | select(.conclusion == "failure")] | length' 2>/dev/null || echo "0") running=$(echo "$runs_json" | jq '[.[] | select(.status == "in_progress")] | length' 2>/dev/null || echo "0") fi # Success rate if [[ $total -gt 0 ]]; then local success_rate=$(awk "BEGIN{printf \"%.1f\", ($success / $total) * 100}") else local success_rate="0.0" fi printf " " c_purple; printf "Total Runs: "; c_reset c_cyan; printf "%s\n" "$total"; c_reset printf " " c_purple; printf "Successful: "; c_reset c_green; printf "%s\n" "$success"; c_reset printf " " c_purple; printf "Failed: "; c_reset c_red; printf "%s\n" "$failure"; c_reset printf " " c_purple; printf "Currently Running: "; c_reset c_yellow; printf "%s\n" "$running"; c_reset printf " " c_purple; printf "Success Rate: "; c_reset if (( $(echo "$success_rate > 90" | bc -l) )); then c_green; printf "%s%%\n" "$success_rate"; c_reset elif (( $(echo "$success_rate > 70" | bc -l) )); then c_yellow; printf "%s%%\n" "$success_rate"; c_reset else c_red; printf "%s%%\n" "$success_rate"; c_reset fi printf "\n" } draw_deployment_status() { c_purple; c_bold printf "╔════════════════════════════════════════════════════════════════════════════════╗\n" printf "║ 🚀 DEPLOYMENT STATUS ║\n" printf "╚════════════════════════════════════════════════════════════════════════════════╝\n" c_reset printf "\n" # Mock deployment data printf " " c_cyan; c_bold; printf "Production: "; c_reset c_green; printf "● Healthy"; c_reset printf " " c_gray; printf "(Last deploy: 2h ago)"; c_reset printf "\n" printf " " c_cyan; c_bold; printf "Staging: "; c_reset c_yellow; printf "● Deploying"; c_reset printf " " c_gray; printf "(In progress)"; c_reset printf "\n" printf " " c_cyan; c_bold; printf "Development: "; c_reset c_green; printf "● Healthy"; c_reset printf " " c_gray; printf "(Last deploy: 15m ago)"; c_reset printf "\n" printf "\n" } draw_footer() { local mode="$1" local timestamp="$2" printf "\n" c_gray printf "═══════════════════════════════════════════════════════════════════════════════\n" if [[ "$mode" == "demo" ]]; then printf "Demo Mode (Mock Data) | Last updated: %s | Press Ctrl+C to exit\n" "$timestamp" else printf "Live GitHub Data | Last updated: %s | Press Ctrl+C to exit\n" "$timestamp" fi c_reset } draw_setup_notice() { c_clear c_yellow; c_bold printf "╔════════════════════════════════════════════════════════════════════════════════╗\n" printf "║ ⚠️ GITHUB CLI NOT CONFIGURED ║\n" printf "╚════════════════════════════════════════════════════════════════════════════════╝\n" c_reset printf "\n" printf "The GitHub CLI is not installed or not authenticated.\n" printf "\n" c_blue; printf "To use live data:\n"; c_reset printf " 1. Install gh CLI: brew install gh\n" printf " 2. Authenticate: gh auth login\n" printf " 3. Run this dashboard again\n" printf "\n" c_green; printf "Running in DEMO MODE with mock data...\n"; c_reset printf "\n" sleep 3 } # ================== # MAIN DASHBOARD # ================== run_dashboard() { local mode="live" local refresh_interval="${1:-10}" # Check dependencies if ! check_gh_cli; then draw_setup_notice mode="demo" fi while true; do draw_header # Get data local runs_json if [[ "$mode" == "demo" ]]; then runs_json=$(generate_mock_runs) else # Try to get real data, fallback to demo runs_json=$(get_workflow_runs "BlackRoad-OS" 10) if [[ -z "$runs_json" ]]; then runs_json=$(generate_mock_runs) mode="demo" fi fi # Draw sections draw_org_summary draw_recent_runs "$runs_json" draw_workflow_stats "$runs_json" draw_deployment_status # Footer local timestamp=$(date "+%Y-%m-%d %H:%M:%S") draw_footer "$mode" "$timestamp" # Wait before refresh sleep "$refresh_interval" done } # ================== # CLI INTERFACE # ================== show_help() { cat <<'HELP' BlackRoad GitHub Actions Monitor USAGE: blackroad-github-dashboard.sh [OPTIONS] OPTIONS: --interval N Refresh interval in seconds (default: 10) --demo Force demo mode with mock data --once Run once and exit (no loop) --help Show this help EXAMPLES: blackroad-github-dashboard.sh # Live dashboard blackroad-github-dashboard.sh --demo # Demo mode blackroad-github-dashboard.sh --once # Single snapshot REQUIREMENTS: • GitHub CLI (brew install gh) • Authenticated with: gh auth login MONITORED DATA: • Repository counts per organization • Workflow counts • Recent workflow runs • Success/failure rates • Deployment status • CI/CD pipeline health Press Ctrl+C to exit live mode. HELP } # ================== # MAIN # ================== main() { local mode="auto" local interval=10 local once=false while [[ $# -gt 0 ]]; do case "$1" in --interval) interval="$2" shift 2 ;; --demo) mode="demo" shift ;; --once) once=true shift ;; --help|-h) show_help exit 0 ;; *) echo "Unknown option: $1" show_help exit 1 ;; esac done if $once; then draw_header local runs_json if [[ "$mode" == "demo" ]] || ! check_gh_cli; then runs_json=$(generate_mock_runs) mode="demo" else runs_json=$(get_workflow_runs "BlackRoad-OS" 10) if [[ -z "$runs_json" ]]; then runs_json=$(generate_mock_runs) mode="demo" fi fi draw_org_summary draw_recent_runs "$runs_json" draw_workflow_stats "$runs_json" draw_deployment_status local timestamp=$(date "+%Y-%m-%d %H:%M:%S") c_gray printf "\nSnapshot taken at %s (%s)\n" "$timestamp" "$mode" c_reset else run_dashboard "$interval" fi } main "$@"