Files
gh-dhofheinz-open-plugins-p…/commands/quality-analysis/.scripts/issue-prioritizer.sh
2025-11-29 18:20:28 +08:00

306 lines
9.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# ============================================================================
# Issue Prioritization Script
# ============================================================================
# Purpose: Categorize and prioritize validation issues into P0/P1/P2 tiers
# Version: 1.0.0
# Usage: ./issue-prioritizer.sh <issues-json-file> [criteria]
# Returns: 0=success, 1=error
# Dependencies: jq, bash 4.0+
# ============================================================================
set -euo pipefail
# Configuration
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly RED='\033[0;31m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m' # No Color
# Priority definitions
declare -A PRIORITY_NAMES=(
[0]="Critical - Must Fix"
[1]="Important - Should Fix"
[2]="Recommended - Nice to Have"
)
declare -A PRIORITY_ICONS=(
[0]="❌"
[1]="⚠️ "
[2]="💡"
)
# Effort labels
declare -A EFFORT_LABELS=(
[low]="Low"
[medium]="Medium"
[high]="High"
)
# Effort time estimates
declare -A EFFORT_TIMES=(
[low]="5-15 minutes"
[medium]="30-60 minutes"
[high]="2+ hours"
)
# ============================================================================
# Functions
# ============================================================================
usage() {
cat <<EOF
Usage: $0 <issues-json-file> [criteria]
Arguments:
issues-json-file Path to JSON file with validation issues
criteria Prioritization criteria: severity|impact|effort (default: severity)
Examples:
$0 validation-results.json
$0 results.json impact
$0 results.json severity
JSON Structure:
{
"errors": [{"type": "...", "severity": "critical", ...}],
"warnings": [{"type": "...", "severity": "important", ...}],
"recommendations": [{"type": "...", "severity": "recommended", ...}]
}
EOF
exit 1
}
check_dependencies() {
local missing_deps=()
if ! command -v jq &> /dev/null; then
missing_deps+=("jq")
fi
if [ ${#missing_deps[@]} -gt 0 ]; then
echo "Error: Missing dependencies: ${missing_deps[*]}" >&2
echo "Install with: sudo apt-get install ${missing_deps[*]}" >&2
return 1
fi
return 0
}
determine_priority() {
local severity="$1"
local type="$2"
# P0 (Critical) - Blocking issues
if [[ "$severity" == "critical" ]] || \
[[ "$type" =~ ^(missing_required|invalid_json|security_vulnerability|format_violation)$ ]]; then
echo "0"
return
fi
# P1 (Important) - Should fix
if [[ "$severity" == "important" ]] || \
[[ "$type" =~ ^(missing_recommended|documentation_gap|convention_violation|performance)$ ]]; then
echo "1"
return
fi
# P2 (Recommended) - Nice to have
echo "2"
}
get_effort_estimate() {
local type="$1"
# High effort
if [[ "$type" =~ ^(security_vulnerability|performance|architecture)$ ]]; then
echo "high"
return
fi
# Medium effort
if [[ "$type" =~ ^(documentation_gap|convention_violation|missing_recommended)$ ]]; then
echo "medium"
return
fi
# Low effort (default)
echo "low"
}
format_issue() {
local priority="$1"
local message="$2"
local impact="${3:-Unknown impact}"
local effort="${4:-low}"
local fix="${5:-No fix suggestion available}"
local icon="${PRIORITY_ICONS[$priority]}"
local effort_label="${EFFORT_LABELS[$effort]}"
local effort_time="${EFFORT_TIMES[$effort]}"
cat <<EOF
${icon} ${message}
Impact: ${impact}
Effort: ${effort_label} (${effort_time})
Fix: ${fix}
EOF
}
process_issues() {
local json_file="$1"
local criteria="${2:-severity}"
# Validate JSON file exists
if [[ ! -f "$json_file" ]]; then
echo "Error: File not found: $json_file" >&2
return 1
fi
# Validate JSON syntax
if ! jq empty "$json_file" 2>/dev/null; then
echo "Error: Invalid JSON in $json_file" >&2
return 1
fi
# Count total issues
local total_errors=$(jq '.errors // [] | length' "$json_file")
local total_warnings=$(jq '.warnings // [] | length' "$json_file")
local total_recommendations=$(jq '.recommendations // [] | length' "$json_file")
local total_issues=$((total_errors + total_warnings + total_recommendations))
if [[ $total_issues -eq 0 ]]; then
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "ISSUE PRIORITIZATION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "No issues found! Quality score is perfect."
return 0
fi
# Initialize priority counters
declare -A priority_counts=([0]=0 [1]=0 [2]=0)
declare -A priority_issues=([0]="" [1]="" [2]="")
# Process errors
while IFS= read -r issue; do
local type=$(echo "$issue" | jq -r '.type // "unknown"')
local severity=$(echo "$issue" | jq -r '.severity // "critical"')
local message=$(echo "$issue" | jq -r '.message // "Unknown error"')
local impact=$(echo "$issue" | jq -r '.impact // "Unknown impact"')
local fix=$(echo "$issue" | jq -r '.fix // "No fix available"')
local score_impact=$(echo "$issue" | jq -r '.score_impact // 0')
local priority=$(determine_priority "$severity" "$type")
local effort=$(get_effort_estimate "$type")
priority_counts[$priority]=$((priority_counts[$priority] + 1))
local formatted_issue=$(format_issue "$priority" "$message" "$impact" "$effort" "$fix")
priority_issues[$priority]+="$formatted_issue"
done < <(jq -c '.errors // [] | .[]' "$json_file")
# Process warnings
while IFS= read -r issue; do
local type=$(echo "$issue" | jq -r '.type // "unknown"')
local severity=$(echo "$issue" | jq -r '.severity // "important"')
local message=$(echo "$issue" | jq -r '.message // "Unknown warning"')
local impact=$(echo "$issue" | jq -r '.impact // "Unknown impact"')
local fix=$(echo "$issue" | jq -r '.fix // "No fix available"')
local priority=$(determine_priority "$severity" "$type")
local effort=$(get_effort_estimate "$type")
priority_counts[$priority]=$((priority_counts[$priority] + 1))
local formatted_issue=$(format_issue "$priority" "$message" "$impact" "$effort" "$fix")
priority_issues[$priority]+="$formatted_issue"
done < <(jq -c '.warnings // [] | .[]' "$json_file")
# Process recommendations
while IFS= read -r issue; do
local type=$(echo "$issue" | jq -r '.type // "unknown"')
local severity=$(echo "$issue" | jq -r '.severity // "recommended"')
local message=$(echo "$issue" | jq -r '.message // "Recommendation"')
local impact=$(echo "$issue" | jq -r '.impact // "Minor quality improvement"')
local fix=$(echo "$issue" | jq -r '.fix // "No fix available"')
local priority=$(determine_priority "$severity" "$type")
local effort=$(get_effort_estimate "$type")
priority_counts[$priority]=$((priority_counts[$priority] + 1))
local formatted_issue=$(format_issue "$priority" "$message" "$impact" "$effort" "$fix")
priority_issues[$priority]+="$formatted_issue"
done < <(jq -c '.recommendations // [] | .[]' "$json_file")
# Display results
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "ISSUE PRIORITIZATION"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Total Issues: $total_issues"
echo ""
# Display each priority tier
for priority in 0 1 2; do
local count=${priority_counts[$priority]}
local name="${PRIORITY_NAMES[$priority]}"
if [[ $count -gt 0 ]]; then
echo "Priority $priority ($name): $count"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "${priority_issues[$priority]}"
fi
done
# Summary
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Summary:"
echo "- Fix P0 issues first (blocking publication)"
echo "- Address P1 issues for quality improvement"
echo "- Consider P2 improvements for excellence"
if [[ ${priority_counts[0]} -gt 0 ]]; then
echo ""
echo "⚠️ WARNING: ${priority_counts[0]} blocking issue(s) must be fixed before publication"
fi
return 0
}
# ============================================================================
# Main
# ============================================================================
main() {
# Check arguments
if [[ $# -lt 1 ]]; then
usage
fi
local json_file="$1"
local criteria="${2:-severity}"
# Check dependencies
if ! check_dependencies; then
return 1
fi
# Validate criteria
if [[ ! "$criteria" =~ ^(severity|impact|effort)$ ]]; then
echo "Error: Invalid criteria '$criteria'. Use: severity|impact|effort" >&2
return 1
fi
# Process issues
process_issues "$json_file" "$criteria"
return 0
}
main "$@"