Enhance QA script output with colors and better formatting

Improvements to output/reporting:
- Color-coded severity levels (red=CRITICAL, yellow=HIGH, blue=MEDIUM, cyan=LOW)
- Progress indicators during scan
- Relative file paths (easier to read)
- Scan duration timing
- Smart category breakdown (only shows categories with issues, sorted by count)
- Better visual hierarchy with bold headers and separators
- Helpful next steps based on results
- Improved footer with useful command examples
- Zero issues now shows green success message

Terminal output is now much easier to scan and understand at a glance
while maintaining plain text format in the report file.
This commit is contained in:
cschantz
2025-12-31 21:47:03 -05:00
parent dcf2ccd414
commit b5f11dcfdb
+169 -45
View File
@@ -61,6 +61,20 @@ if [ ! -d "$TOOLKIT_PATH" ]; then
exit 1
fi
# Colors for output (only if terminal)
if [ -t 1 ]; then
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
BOLD='\033[1m'
DIM='\033[2m'
NC='\033[0m'
else
RED='' YELLOW='' BLUE='' GREEN='' CYAN='' BOLD='' DIM='' NC=''
fi
# Output file for easy review
REPORT="/tmp/qa-report.txt"
> "$REPORT"
@@ -69,6 +83,18 @@ REPORT="/tmp/qa-report.txt"
TEMP_COUNTS="/tmp/qa-counts.$$"
echo "0 0 0 0" > "$TEMP_COUNTS"
# Track check timing
START_TIME=$(date +%s)
# Progress indicator
show_progress() {
local check_num="$1"
local check_name="$2"
if [ -t 1 ] && ! $SUMMARY_MODE; then
printf "\r${DIM}[%2d/88] ${NC}%s${DIM}...${NC}" "$check_num" "$check_name"
fi
}
# Helper to increment counters (avoids subshell issue)
count_issue() {
local severity="$1"
@@ -3197,9 +3223,17 @@ echo ""
#==============================================================================
# SUMMARY
#==============================================================================
# Clear progress line
if [ -t 1 ]; then
printf "\r%80s\r" " "
fi
read crit high med low < "$TEMP_COUNTS"
total=$((crit + high + med + low))
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
# Write plain summary to file
{
echo "═══════════════════════════════════════════════════════════════"
echo "SUMMARY"
@@ -3211,9 +3245,42 @@ echo " MEDIUM: $med"
echo " LOW: $low"
echo ""
echo "Files Scanned: $(find "$TOOLKIT_PATH" -name "*.sh" 2>/dev/null | wc -l)"
echo "Scan Duration: ${DURATION}s"
echo "Report: $REPORT"
echo "═══════════════════════════════════════════════════════════════"
} | tee -a "$REPORT"
} >> "$REPORT"
# Display colored summary to terminal
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${BOLD} QA SCAN RESULTS${NC}"
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
echo ""
echo -e "${BOLD}Total Issues:${NC} $total"
if [ "$crit" -gt 0 ]; then
echo -e " ${RED}${BOLD}CRITICAL:${NC} ${RED}$crit${NC} ${DIM}(must fix immediately)${NC}"
else
echo -e " ${DIM}CRITICAL: 0${NC}"
fi
if [ "$high" -gt 0 ]; then
echo -e " ${YELLOW}HIGH:${NC} ${YELLOW}$high${NC} ${DIM}(fix soon)${NC}"
else
echo -e " ${DIM}HIGH: 0${NC}"
fi
if [ "$med" -gt 0 ]; then
echo -e " ${BLUE}MEDIUM:${NC} ${BLUE}$med${NC} ${DIM}(review when possible)${NC}"
else
echo -e " ${DIM}MEDIUM: 0${NC}"
fi
if [ "$low" -gt 0 ]; then
echo -e " ${CYAN}LOW:${NC} ${CYAN}$low${NC} ${DIM}(minor issues)${NC}"
else
echo -e " ${DIM}LOW: 0${NC}"
fi
echo ""
echo -e "${DIM}Files Scanned: $(find "$TOOLKIT_PATH" -name "*.sh" 2>/dev/null | wc -l)${NC}"
echo -e "${DIM}Scan Duration: ${DURATION}s${NC}"
echo -e "${DIM}Full Report: $REPORT${NC}"
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
# Summary mode: just show counts and exit
if $SUMMARY_MODE; then
@@ -3234,66 +3301,123 @@ if $SUMMARY_MODE; then
fi
echo ""
echo "DETAILED BREAKDOWN BY SEVERITY:"
echo -e "${BOLD}DETAILED BREAKDOWN BY SEVERITY:${NC}"
echo ""
# Group and display by severity
echo "CRITICAL ISSUES ($crit):"
grep "^CRITICAL|" "$REPORT" | while IFS='|' read -r sev file line issue; do
printf " %s:%s - %s\n" "$file" "$line" "$issue"
done
echo ""
echo "HIGH ISSUES ($high):"
grep "^HIGH|" "$REPORT" | head -15 | while IFS='|' read -r sev file line issue; do
printf " %s:%s - %s\n" "$file" "$line" "$issue"
done
if [ "$high" -gt 15 ]; then
echo " ... and $((high - 15)) more (see $REPORT)"
fi
echo ""
echo "MEDIUM ISSUES ($med):"
grep "^MEDIUM|" "$REPORT" | head -10 | while IFS='|' read -r sev file line issue; do
printf " %s:%s - %s\n" "$file" "$line" "$issue"
done
if [ "$med" -gt 10 ]; then
echo " ... and $((med - 10)) more (see $REPORT)"
fi
echo ""
echo "LOW ISSUES ($low):"
grep "^LOW|" "$REPORT" | head -5 | while IFS='|' read -r sev file line issue; do
printf " %s:%s - %s\n" "$file" "$line" "$issue"
done
if [ "$low" -gt 5 ]; then
echo " ... and $((low - 5)) more (see $REPORT)"
# Group and display by severity with colors
if [ "$crit" -gt 0 ]; then
echo -e "${RED}${BOLD}CRITICAL ISSUES ($crit):${NC}"
grep "^CRITICAL|" "$REPORT" | while IFS='|' read -r sev file line issue; do
# Simplify file path (relative to toolkit)
rel_file="${file#$TOOLKIT_PATH/}"
printf " ${RED}${NC} %s:%s ${DIM}-${NC} %s\n" "$rel_file" "$line" "$issue"
done
echo ""
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo "CATEGORY BREAKDOWN (Top Issues by Type):"
echo "═══════════════════════════════════════════════════════════════"
if [ "$high" -gt 0 ]; then
echo -e "${YELLOW}HIGH ISSUES ($high):${NC}"
grep "^HIGH|" "$REPORT" | head -15 | while IFS='|' read -r sev file line issue; do
rel_file="${file#$TOOLKIT_PATH/}"
printf " ${YELLOW}${NC} %s:%s ${DIM}-${NC} %s\n" "$rel_file" "$line" "$issue"
done
if [ "$high" -gt 15 ]; then
echo -e " ${DIM}... and $((high - 15)) more (see $REPORT)${NC}"
fi
echo ""
fi
if [ "$med" -gt 0 ]; then
echo -e "${BLUE}MEDIUM ISSUES ($med):${NC}"
grep "^MEDIUM|" "$REPORT" | head -10 | while IFS='|' read -r sev file line issue; do
rel_file="${file#$TOOLKIT_PATH/}"
printf " ${BLUE}${NC} %s:%s ${DIM}-${NC} %s\n" "$rel_file" "$line" "$issue"
done
if [ "$med" -gt 10 ]; then
echo -e " ${DIM}... and $((med - 10)) more (see $REPORT)${NC}"
fi
echo ""
fi
if [ "$low" -gt 0 ]; then
echo -e "${CYAN}LOW ISSUES ($low):${NC}"
grep "^LOW|" "$REPORT" | head -5 | while IFS='|' read -r sev file line issue; do
rel_file="${file#$TOOLKIT_PATH/}"
printf " ${CYAN}${NC} %s:%s ${DIM}-${NC} %s\n" "$rel_file" "$line" "$issue"
done
if [ "$low" -gt 5 ]; then
echo -e " ${DIM}... and $((low - 5)) more (see $REPORT)${NC}"
fi
echo ""
fi
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${BOLD}TOP ISSUES BY CATEGORY:${NC}"
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
# Create array of category counts
declare -A cat_counts
for tag in SQL-INJ CMD-INJ PANEL-CALL FILE-OP SECRET-LEAK RACE SOURCE RETURN NULL DEP TEMP SUBSHELL PIPE WORDSPLIT ARITH TEST REDIR TRAP ARRAY HEREDOC IF-MASK NUMCMP BG-JOB LOCALE PROC-SUB PRINTF REGEX BASHISM ESCAPE SLEEP-RACE IFS SUBSHELL-VAR TRAP-RACE PERF-LOOP PERF-CACHE PERF-READ RECURSION FD-LEAK ZOMBIE DISK-SPACE NET-TIMEOUT LOG-ROTATE CPU-LOOP HARDCODED-PATH MISSING-LIB USERDATA-ACCESS API-CHECK NO-CASE DB-PATTERN NO-USER-MGR NO-STANDALONE; do
count=$(grep -c "\[$tag\]" "$REPORT" 2>/dev/null || echo 0)
if [ "$count" -gt 0 ]; then
printf " %-12s: %d issues\n" "$tag" "$count"
cat_counts[$tag]=$count
fi
done
# Sort and display (show top 15)
if [ ${#cat_counts[@]} -gt 0 ]; then
for tag in "${!cat_counts[@]}"; do
echo "${cat_counts[$tag]} $tag"
done | sort -rn | head -15 | while read count tag; do
# Color code based on severity keywords
if [[ "$tag" =~ (SQL-INJ|CMD-INJ|SECRET) ]]; then
printf " ${RED}%-20s${NC} %s\n" "$tag" "${CYAN}$count issues${NC}"
elif [[ "$tag" =~ (FILE-OP|RACE|PANEL) ]]; then
printf " ${YELLOW}%-20s${NC} %s\n" "$tag" "${CYAN}$count issues${NC}"
else
printf " ${DIM}%-20s${NC} %s\n" "$tag" "${CYAN}$count issues${NC}"
fi
done
total_cats=${#cat_counts[@]}
if [ "$total_cats" -gt 15 ]; then
echo -e " ${DIM}... and $((total_cats - 15)) more categories (see $REPORT)${NC}"
fi
else
echo -e " ${GREEN}No issues found!${NC}"
fi
echo ""
# Cleanup
rm -f "$TEMP_COUNTS"
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${BOLD}NEXT STEPS:${NC}"
echo -e "${BOLD}═══════════════════════════════════════════════════════════════${NC}"
echo ""
echo "Full report saved to: $REPORT"
if [ "$total" -eq 0 ]; then
echo -e " ${GREEN}${NC} Code quality looks good!"
echo -e " ${DIM}No issues found in this scan${NC}"
elif [ "$crit" -gt 0 ]; then
echo -e " ${RED}!${NC} Fix ${RED}CRITICAL${NC} issues immediately"
echo -e " ${DIM}Use: grep '^CRITICAL' $REPORT${NC}"
elif [ "$high" -gt 0 ]; then
echo -e " ${YELLOW}!${NC} Review ${YELLOW}HIGH${NC} priority issues soon"
echo -e " ${DIM}Use: grep '^HIGH' $REPORT${NC}"
else
echo -e " ${BLUE}${NC} Review and fix issues when possible"
fi
echo ""
echo "Quick Filter Examples:"
echo " --quick Show CRITICAL + HIGH only (faster)"
echo " --security Security issues only"
echo " --category SQL-INJ SQL injection issues only"
echo " --summary Just counts, no details"
echo -e "${DIM}Full report: $REPORT${NC}"
echo ""
echo -e "${BOLD}Useful Commands:${NC}"
echo -e " ${CYAN}$0 --quick${NC} ${DIM}# Fast scan (CRITICAL + HIGH only)${NC}"
echo -e " ${CYAN}$0 --security${NC} ${DIM}# Security issues only${NC}"
echo -e " ${CYAN}$0 --category SQL-INJ${NC} ${DIM}# Filter by category${NC}"
echo -e " ${CYAN}$0 --summary${NC} ${DIM}# Show counts only${NC}"
echo -e " ${CYAN}grep '^CRITICAL' $REPORT${NC} ${DIM}# View all critical issues${NC}"
echo ""
echo -e "${DIM}Scan completed in ${DURATION}s | Exit code: $total${NC}"
echo ""
echo "Exit code: $total"
exit $total