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:
+169
-45
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user