UNPKG

@cloudkinetix/bmad-enhanced

Version:

Cloud-Kinetix enhanced fork of BMAD-METHOD - Breakthrough Method of Agile AI-driven Development with robust versioning and unified validation.

366 lines (295 loc) â€ĸ 11 kB
# CI Status Parser Utility ## Intelligent GitLab CI/CD Data Parsing and Formatting This utility provides standardized parsing and formatting of GitLab CI/CD data for consistent consumption across the expansion pack and integration with other BMAD components. ## Core Parsing Functions ### Pipeline Status Parsing #### Extract Pipeline Summary ```bash # Parse pipeline data into standardized summary format parse_pipeline_summary() { local branch=${1:-$(git branch --show-current)} local format=${2:-"standard"} # standard, json, csv, jira-comment local PIPELINE_DATA=$(glab ci get --output json --branch "$branch" 2>/dev/null) if [ $? -eq 0 ] && [ "$PIPELINE_DATA" != "" ]; then # Extract core fields local ID=$(echo "$PIPELINE_DATA" | jq -r '.id // "unknown"') local STATUS=$(echo "$PIPELINE_DATA" | jq -r '.status // "unknown"') local REF=$(echo "$PIPELINE_DATA" | jq -r '.ref // "unknown"') local DURATION=$(echo "$PIPELINE_DATA" | jq -r '.duration // 0') local WEB_URL=$(echo "$PIPELINE_DATA" | jq -r '.web_url // ""') local CREATED_AT=$(echo "$PIPELINE_DATA" | jq -r '.created_at // ""') local UPDATED_AT=$(echo "$PIPELINE_DATA" | jq -r '.updated_at // ""') case "$format" in "json") echo "{\"id\":\"$ID\",\"status\":\"$STATUS\",\"ref\":\"$REF\",\"duration\":$DURATION,\"web_url\":\"$WEB_URL\",\"created_at\":\"$CREATED_AT\",\"updated_at\":\"$UPDATED_AT\"}" ;; "csv") echo "$ID,$STATUS,$REF,$DURATION,$WEB_URL,$CREATED_AT,$UPDATED_AT" ;; "jira-comment") echo "🔄 *CI Pipeline Status*" echo "" echo "â€ĸ *Status:* $STATUS" echo "â€ĸ *Branch:* $REF" echo "â€ĸ *Duration:* ${DURATION}s" echo "â€ĸ *Pipeline:* [$ID|$WEB_URL]" echo "â€ĸ *Updated:* $UPDATED_AT" ;; *) echo "Pipeline Summary:" echo "==================" echo "ID: $ID" echo "Status: $STATUS" echo "Branch: $REF" echo "Duration: ${DURATION}s" echo "URL: $WEB_URL" echo "Created: $CREATED_AT" echo "Updated: $UPDATED_AT" ;; esac else case "$format" in "json") echo '{"error":"no_pipeline_data"}' ;; "csv") echo "error,no_pipeline_data,,,,,," ;; *) echo "No pipeline data available for branch: $branch" ;; esac fi } ``` #### Extract Job Status Summary ```bash # Parse job statuses into organized summary parse_job_summary() { local branch=${1:-$(git branch --show-current)} local format=${2:-"standard"} local PIPELINE_DATA=$(glab ci get --output json --branch "$branch" 2>/dev/null) if [ $? -eq 0 ] && [ "$PIPELINE_DATA" != "" ]; then case "$format" in "json") echo "$PIPELINE_DATA" | jq -r '.jobs[] | {name: .name, status: .status, stage: .stage, duration: .duration}' ;; "csv") echo "name,status,stage,duration" echo "$PIPELINE_DATA" | jq -r '.jobs[] | "\(.name),\(.status),\(.stage),\(.duration // 0)"' ;; "jira-comment") echo "📋 *Job Status Summary*" echo "" # Group by status local SUCCESS_JOBS=$(echo "$PIPELINE_DATA" | jq -r '.jobs[] | select(.status == "success") | .name' | wc -l) local FAILED_JOBS=$(echo "$PIPELINE_DATA" | jq -r '.jobs[] | select(.status == "failed") | .name' | wc -l) local RUNNING_JOBS=$(echo "$PIPELINE_DATA" | jq -r '.jobs[] | select(.status == "running") | .name' | wc -l) local PENDING_JOBS=$(echo "$PIPELINE_DATA" | jq -r '.jobs[] | select(.status == "pending") | .name' | wc -l) echo "â€ĸ ✅ Successful: $SUCCESS_JOBS" echo "â€ĸ ❌ Failed: $FAILED_JOBS" echo "â€ĸ 🔄 Running: $RUNNING_JOBS" echo "â€ĸ âŗ Pending: $PENDING_JOBS" # List failed jobs if any if [ "$FAILED_JOBS" -gt 0 ]; then echo "" echo "*Failed Jobs:*" echo "$PIPELINE_DATA" | jq -r '.jobs[] | select(.status == "failed") | "â€ĸ \(.name)"' fi ;; *) echo "Job Status Summary:" echo "==================" echo "$PIPELINE_DATA" | jq -r '.jobs[] | "\(.name): \(.status) (\(.stage)) - \(.duration // 0)s"' echo "" echo "Status Counts:" echo "$PIPELINE_DATA" | jq -r '.jobs[] | .status' | sort | uniq -c | sort -nr ;; esac else case "$format" in "json") echo '{"error":"no_job_data"}' ;; "csv") echo "error,no_job_data,,," ;; *) echo "No job data available for branch: $branch" ;; esac fi } ``` ### Status Conversion Functions #### Convert Status to Emoji ```bash # Convert CI status to emoji representation status_to_emoji() { local status="$1" case "$status" in "success"|"passed") echo "✅" ;; "failed"|"failure") echo "❌" ;; "running"|"started") echo "🔄" ;; "pending"|"created") echo "âŗ" ;; "canceled"|"cancelled") echo "âšī¸" ;; "skipped") echo "â­ī¸" ;; "manual") echo "🤏" ;; "scheduled") echo "📅" ;; *) echo "❓" ;; esac } ``` #### Convert Status to Color Code ```bash # Convert CI status to color codes for terminal output status_to_color() { local status="$1" case "$status" in "success"|"passed") echo "\033[0;32m" ;; # Green "failed"|"failure") echo "\033[0;31m" ;; # Red "running"|"started") echo "\033[0;34m" ;; # Blue "pending"|"created") echo "\033[0;33m" ;; # Yellow "canceled"|"cancelled") echo "\033[0;90m" ;; # Gray "skipped") echo "\033[0;36m" ;; # Cyan *) echo "\033[0m" ;; # Reset esac } ``` #### Convert Duration to Human Readable ```bash # Convert duration seconds to human readable format format_duration() { local seconds="$1" if [ "$seconds" = "null" ] || [ -z "$seconds" ] || [ "$seconds" = "0" ]; then echo "0s" return fi local hours=$((seconds / 3600)) local minutes=$(((seconds % 3600) / 60)) local secs=$((seconds % 60)) if [ "$hours" -gt 0 ]; then echo "${hours}h ${minutes}m ${secs}s" elif [ "$minutes" -gt 0 ]; then echo "${minutes}m ${secs}s" else echo "${secs}s" fi } ``` ## Integration-Specific Parsing ### JIRA Integration Formatting ```bash # Format pipeline status for JIRA comment/description format_for_jira() { local branch=${1:-$(git branch --show-current)} echo "h3. 🔄 GitLab CI/CD Status" echo "" # Pipeline summary in JIRA format parse_pipeline_summary "$branch" "jira-comment" echo "" # Job summary in JIRA format parse_job_summary "$branch" "jira-comment" echo "" # Add timestamp echo "_{color:gray}Last updated: $(date){color}_" } ``` ### Parallel Development Coordination Format ```bash # Format CI status for parallel development coordination format_for_parallel_dev() { echo "Parallel Development CI Status" echo "=============================" # Check multiple worktrees if they exist if command -v git >/dev/null 2>&1; then git worktree list 2>/dev/null | while read worktree_info; do local WORKTREE_PATH=$(echo "$worktree_info" | awk '{print $1}') local BRANCH=$(echo "$worktree_info" | awk '{print $3}' | tr -d '[]') if [ -n "$BRANCH" ] && [ "$BRANCH" != "detached" ]; then echo "" echo "Branch: $BRANCH" echo "Path: $WORKTREE_PATH" # Get CI status for this branch local STATUS=$(glab ci get --output json --branch "$BRANCH" 2>/dev/null | jq -r '.status // "no-pipeline"') local EMOJI=$(status_to_emoji "$STATUS") echo "CI Status: $EMOJI $STATUS" # Show job summary if pipeline exists if [ "$STATUS" != "no-pipeline" ]; then local FAILED_COUNT=$(glab ci get --output json --branch "$BRANCH" 2>/dev/null | jq -r '.jobs[] | select(.status == "failed") | .name' | wc -l) local TOTAL_COUNT=$(glab ci get --output json --branch "$BRANCH" 2>/dev/null | jq -r '.jobs[] | .name' | wc -l) echo "Jobs: $((TOTAL_COUNT - FAILED_COUNT))/$TOTAL_COUNT passing" fi fi done else echo "Git not available for worktree analysis" fi } ``` ## Data Export Functions ### Export to CSV ```bash # Export pipeline and job data to CSV format export_to_csv() { local branch=${1:-$(git branch --show-current)} local output_file=${2:-"ci_status_$(date +%Y%m%d_%H%M%S).csv"} echo "Exporting CI data to: $output_file" # Pipeline header echo "=== PIPELINE DATA ===" > "$output_file" echo "id,status,ref,duration,web_url,created_at,updated_at" >> "$output_file" parse_pipeline_summary "$branch" "csv" >> "$output_file" # Job data echo "" >> "$output_file" echo "=== JOB DATA ===" >> "$output_file" parse_job_summary "$branch" "csv" >> "$output_file" echo "Export completed: $output_file" } ``` ### Export to JSON ```bash # Export comprehensive CI data to JSON format export_to_json() { local branch=${1:-$(git branch --show-current)} local output_file=${2:-"ci_status_$(date +%Y%m%d_%H%M%S).json"} local PIPELINE_DATA=$(glab ci get --output json --branch "$branch" 2>/dev/null) if [ $? -eq 0 ] && [ "$PIPELINE_DATA" != "" ]; then # Add metadata echo "{" > "$output_file" echo " \"export_timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> "$output_file" echo " \"branch\": \"$branch\"," >> "$output_file" echo " \"pipeline_data\": $PIPELINE_DATA" >> "$output_file" echo "}" >> "$output_file" echo "JSON export completed: $output_file" else echo "No pipeline data available for JSON export" fi } ``` ## Health Check Functions ### Quick Status Check ```bash # Quick one-line status check quick_status() { local branch=${1:-$(git branch --show-current)} local STATUS=$(glab ci get --output json --branch "$branch" 2>/dev/null | jq -r '.status // "no-pipeline"') local EMOJI=$(status_to_emoji "$STATUS") local FAILED_JOBS=$(glab ci get --output json --branch "$branch" 2>/dev/null | jq -r '.jobs[] | select(.status == "failed") | .name' | wc -l) if [ "$STATUS" = "no-pipeline" ]; then echo "âšĒ No pipeline found for branch: $branch" elif [ "$FAILED_JOBS" -gt 0 ]; then echo "$EMOJI $STATUS ($FAILED_JOBS failed jobs) - $branch" else echo "$EMOJI $STATUS - $branch" fi } ``` ## Usage Examples ```bash # Standard pipeline summary parse_pipeline_summary main # Job summary in JSON format parse_job_summary develop json # JIRA-formatted status format_for_jira feature-branch # Quick status check quick_status # Export to CSV export_to_csv main ci_report.csv # Parallel development status format_for_parallel_dev ``` ## Integration Notes - **JIRA Integration**: Use format_for_jira() for JIRA comment updates - **Parallel Development**: Use format_for_parallel_dev() for multi-worktree coordination - **Automation**: All functions designed for non-interactive operation - **Error Handling**: Graceful fallbacks for missing data - **Format Flexibility**: Multiple output formats for different consumption needs