197 lines
6.6 KiB
Bash
Executable File
197 lines
6.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Universal QA hook handler with robust error handling
|
|
# Location: ~/.mosaic/rails/qa-hook-handler.sh
|
|
|
|
# Don't exit on unset variables initially to handle missing params gracefully
|
|
set -eo pipefail
|
|
|
|
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
TOOL_NAME="${1:-}"
|
|
FILE_PATH="${2:-}"
|
|
|
|
# Debug logging
|
|
echo "[DEBUG] Script called with args: \$1='$1' \$2='$2'" >> "$PROJECT_ROOT/logs/qa-automation.log" 2>/dev/null || true
|
|
|
|
# Validate inputs
|
|
if [ -z "$FILE_PATH" ] || [ -z "$TOOL_NAME" ]; then
|
|
echo "[ERROR] Missing required parameters: tool='$TOOL_NAME' file='$FILE_PATH'" >&2
|
|
echo "[ERROR] Usage: $0 <tool> <file_path>" >&2
|
|
# Log to file if possible
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] Missing parameters - tool='$TOOL_NAME' file='$FILE_PATH'" >> "$PROJECT_ROOT/logs/qa-automation.log" 2>/dev/null || true
|
|
exit 1
|
|
fi
|
|
|
|
# Now enable strict mode after parameter handling
|
|
set -u
|
|
|
|
# Skip non-JS/TS files
|
|
if ! [[ "$FILE_PATH" =~ \.(ts|tsx|js|jsx|mjs|cjs)$ ]]; then
|
|
echo "[INFO] Skipping non-JS/TS file: $FILE_PATH"
|
|
exit 0
|
|
fi
|
|
|
|
# Generate naming components
|
|
TIMESTAMP=$(date '+%Y%m%d-%H%M')
|
|
SANITIZED_NAME=$(echo "$FILE_PATH" | sed 's/\//-/g' | sed 's/^-//' | sed 's/\.\./\./g')
|
|
ITERATION=1
|
|
|
|
# Log file for debugging
|
|
LOG_FILE="$PROJECT_ROOT/logs/qa-automation.log"
|
|
mkdir -p "$(dirname "$LOG_FILE")"
|
|
|
|
# Function to detect Epic with fallback
|
|
detect_epic() {
|
|
local file_path="$1"
|
|
local epic=""
|
|
|
|
# Try to detect Epic from path patterns
|
|
case "$file_path" in
|
|
*/apps/frontend/src/components/*adapter*|*/apps/frontend/src/views/*adapter*)
|
|
epic="E.3001-ADAPTER-CONFIG-SYSTEM"
|
|
;;
|
|
*/services/backend/src/adapters/*)
|
|
epic="E.3001-ADAPTER-CONFIG-SYSTEM"
|
|
;;
|
|
*/services/backend/src/*)
|
|
epic="E.2004-enterprise-data-synchronization-engine"
|
|
;;
|
|
*/services/syncagent-debezium/*|*/services/syncagent-n8n/*)
|
|
epic="E.2004-enterprise-data-synchronization-engine"
|
|
;;
|
|
*)
|
|
epic="" # General QA
|
|
;;
|
|
esac
|
|
|
|
echo "$epic"
|
|
}
|
|
|
|
# Detect Epic association
|
|
EPIC_FOLDER=$(detect_epic "$FILE_PATH")
|
|
|
|
# Function to setup report directory with creation if needed
|
|
setup_report_dir() {
|
|
local epic="$1"
|
|
local project_root="$2"
|
|
local report_dir=""
|
|
|
|
if [ -n "$epic" ]; then
|
|
# Check if Epic directory exists
|
|
local epic_dir="$project_root/docs/task-management/epics/active/$epic"
|
|
|
|
if [ -d "$epic_dir" ]; then
|
|
# Epic exists, use it
|
|
report_dir="$epic_dir/reports/qa-automation/pending"
|
|
echo "[INFO] Using existing Epic: $epic" | tee -a "$LOG_FILE"
|
|
else
|
|
# Epic doesn't exist, check if we should create it
|
|
local epic_parent="$project_root/docs/task-management/epics/active"
|
|
|
|
if [ -d "$epic_parent" ]; then
|
|
# Parent exists, create Epic structure
|
|
echo "[WARN] Epic $epic not found, creating structure..." | tee -a "$LOG_FILE"
|
|
mkdir -p "$epic_dir/reports/qa-automation/pending"
|
|
mkdir -p "$epic_dir/reports/qa-automation/in-progress"
|
|
mkdir -p "$epic_dir/reports/qa-automation/done"
|
|
mkdir -p "$epic_dir/reports/qa-automation/escalated"
|
|
|
|
# Create Epic README
|
|
cat > "$epic_dir/README.md" << EOF
|
|
# Epic: $epic
|
|
|
|
**Status**: Active
|
|
**Created**: $(date '+%Y-%m-%d')
|
|
**Purpose**: Auto-created by QA automation system
|
|
|
|
## Description
|
|
This Epic was automatically created to organize QA remediation reports.
|
|
|
|
## QA Automation
|
|
- Reports are stored in \`reports/qa-automation/\`
|
|
- Pending issues: \`reports/qa-automation/pending/\`
|
|
- Escalated issues: \`reports/qa-automation/escalated/\`
|
|
EOF
|
|
report_dir="$epic_dir/reports/qa-automation/pending"
|
|
echo "[INFO] Created Epic structure: $epic" | tee -a "$LOG_FILE"
|
|
else
|
|
# Epic structure doesn't exist, fall back to general
|
|
echo "[WARN] Epic structure not found, using general QA" | tee -a "$LOG_FILE"
|
|
report_dir="$project_root/docs/reports/qa-automation/pending"
|
|
fi
|
|
fi
|
|
else
|
|
# No Epic association, use general
|
|
report_dir="$project_root/docs/reports/qa-automation/pending"
|
|
echo "[INFO] No Epic association, using general QA" | tee -a "$LOG_FILE"
|
|
fi
|
|
|
|
# Ensure directory exists
|
|
mkdir -p "$report_dir"
|
|
echo "$report_dir"
|
|
}
|
|
|
|
# Setup report directory (capture only the last line which is the path)
|
|
REPORT_DIR=$(setup_report_dir "$EPIC_FOLDER" "$PROJECT_ROOT" | tail -1)
|
|
|
|
# Check for existing reports from same timestamp
|
|
check_existing_iteration() {
|
|
local dir="$1"
|
|
local name="$2"
|
|
local timestamp="$3"
|
|
local max_iter=0
|
|
|
|
for file in "$dir"/${name}_${timestamp}_*_remediation_needed.md; do
|
|
if [ -f "$file" ]; then
|
|
# Extract iteration number
|
|
local iter=$(echo "$file" | sed 's/.*_\([0-9]\+\)_remediation_needed\.md$/\1/')
|
|
if [ "$iter" -gt "$max_iter" ]; then
|
|
max_iter=$iter
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo $((max_iter + 1))
|
|
}
|
|
|
|
ITERATION=$(check_existing_iteration "$REPORT_DIR" "$SANITIZED_NAME" "$TIMESTAMP")
|
|
|
|
# Check if we're at max iterations
|
|
if [ "$ITERATION" -gt 5 ]; then
|
|
echo "[ERROR] Max iterations (5) reached for $FILE_PATH" | tee -a "$LOG_FILE"
|
|
# Move to escalated immediately
|
|
REPORT_DIR="${REPORT_DIR/pending/escalated}"
|
|
mkdir -p "$REPORT_DIR"
|
|
ITERATION=5 # Cap at 5
|
|
fi
|
|
|
|
# Create report filename
|
|
REPORT_FILE="${SANITIZED_NAME}_${TIMESTAMP}_${ITERATION}_remediation_needed.md"
|
|
REPORT_PATH="$REPORT_DIR/$REPORT_FILE"
|
|
|
|
# Log the action
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] QA Hook: $TOOL_NAME on $FILE_PATH" | tee -a "$LOG_FILE"
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Creating report: $REPORT_PATH" | tee -a "$LOG_FILE"
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Epic: ${EPIC_FOLDER:-general}, Iteration: $ITERATION" | tee -a "$LOG_FILE"
|
|
|
|
# Create a task file for the QA agent instead of calling Claude directly
|
|
cat > "$REPORT_PATH" << EOF
|
|
# QA Remediation Report
|
|
|
|
**File:** $FILE_PATH
|
|
**Tool Used:** $TOOL_NAME
|
|
**Epic:** ${EPIC_FOLDER:-general}
|
|
**Iteration:** $ITERATION
|
|
**Generated:** $(date '+%Y-%m-%d %H:%M:%S')
|
|
|
|
## Status
|
|
Pending QA validation
|
|
|
|
## Next Steps
|
|
This report was created by the QA automation hook.
|
|
To process this report, run:
|
|
\`\`\`bash
|
|
claude -p "Use Task tool to launch universal-qa-agent for report: $REPORT_PATH"
|
|
\`\`\`
|
|
EOF
|
|
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Created report template at: $REPORT_PATH" | tee -a "$LOG_FILE" |