109 lines
4.6 KiB
Bash
Executable File
109 lines
4.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# ╔═══════════════════════════════════════════════════════════════╗
|
|
# ║ 🔐 DEPLOY VALIDATOR — Pre-deploy integrity check ║
|
|
# ║ Usage: deploy-validator.sh <file> [target_dir] ║
|
|
# ║ Returns 0 if safe, 1 if blocked ║
|
|
# ║ Must pass ALL checks before any file is deployed ║
|
|
# ╚═══════════════════════════════════════════════════════════════╝
|
|
|
|
FILE="$1"
|
|
TARGET="${2:-/opt/wevads/public}"
|
|
VAULT="/opt/wevads/vault"
|
|
LOG="/opt/wevads/logs/deploy-validator.log"
|
|
|
|
if [ -z "$FILE" ]; then
|
|
echo '{"ok":false,"error":"Usage: deploy-validator.sh <file> [target_dir]"}'
|
|
exit 1
|
|
fi
|
|
|
|
fname=$(basename "$FILE")
|
|
ext="${fname##*.}"
|
|
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
|
ERRORS=""
|
|
WARNINGS=""
|
|
new_size=$(wc -c < "$FILE" 2>/dev/null || echo 0)
|
|
|
|
log() { echo "[$TIMESTAMP] $1" >> "$LOG"; }
|
|
|
|
# ═══════════════════════════════════════
|
|
# CHECK 1: File exists and has content
|
|
# ═══════════════════════════════════════
|
|
if [ ! -f "$FILE" ]; then
|
|
echo '{"ok":false,"error":"File not found: '"$FILE"'"}'
|
|
exit 1
|
|
fi
|
|
if [ "$new_size" -lt 100 ]; then
|
|
echo '{"ok":false,"error":"File too small: '"$new_size"'B (min 100B)"}'
|
|
exit 1
|
|
fi
|
|
|
|
# ═══════════════════════════════════════
|
|
# CHECK 2: HTML-specific validations
|
|
# ═══════════════════════════════════════
|
|
if [ "$ext" = "html" ]; then
|
|
# Must have closing tags
|
|
if [ "$new_size" -gt 5000 ]; then
|
|
has_close_html=$(grep -c '</html>' "$FILE")
|
|
has_style=$(grep -c '<style' "$FILE")
|
|
has_script=$(grep -c '<script' "$FILE")
|
|
has_close_script=$(grep -c '</script>' "$FILE")
|
|
|
|
[ "$has_close_html" -eq 0 ] && ERRORS="${ERRORS}missing_close_html "
|
|
[ "$has_style" -eq 0 ] && WARNINGS="${WARNINGS}no_css "
|
|
[ "$has_script" -gt 0 ] && [ "$has_close_script" -eq 0 ] && ERRORS="${ERRORS}unclosed_script "
|
|
|
|
# Check onclick without script
|
|
has_onclick=$(grep -cE 'onclick|oninput' "$FILE")
|
|
[ "$has_onclick" -gt 0 ] && [ "$has_script" -eq 0 ] && ERRORS="${ERRORS}onclick_no_script "
|
|
fi
|
|
|
|
# Size regression check vs gold
|
|
gold="$VAULT/${fname}.gold"
|
|
if [ -f "$gold" ]; then
|
|
gold_size=$(wc -c < "$gold")
|
|
if [ "$gold_size" -gt 1000 ] && [ "$new_size" -lt "$((gold_size * 50 / 100))" ]; then
|
|
ERRORS="${ERRORS}size_regression(gold=${gold_size}B,new=${new_size}B) "
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ═══════════════════════════════════════
|
|
# CHECK 3: PHP syntax validation
|
|
# ═══════════════════════════════════════
|
|
if [ "$ext" = "php" ]; then
|
|
result=$(php -l "$FILE" 2>&1)
|
|
if echo "$result" | grep -q 'Parse error\|Fatal'; then
|
|
ERRORS="${ERRORS}php_syntax_error "
|
|
fi
|
|
|
|
# Size regression vs gold
|
|
goldname=$(echo "$TARGET/$fname" | sed 's|/|__|g' | sed 's|^__||').gold
|
|
gold="$VAULT/$goldname"
|
|
if [ -f "$gold" ]; then
|
|
gold_size=$(wc -c < "$gold")
|
|
if [ "$gold_size" -gt 1000 ] && [ "$new_size" -lt "$((gold_size * 50 / 100))" ]; then
|
|
ERRORS="${ERRORS}size_regression(gold=${gold_size}B,new=${new_size}B) "
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ═══════════════════════════════════════
|
|
# VERDICT
|
|
# ═══════════════════════════════════════
|
|
if [ -n "$ERRORS" ]; then
|
|
log "BLOCKED: $fname — $ERRORS"
|
|
echo '{"ok":false,"file":"'"$fname"'","size":'"$new_size"',"errors":"'"$ERRORS"'","warnings":"'"$WARNINGS"'"}'
|
|
exit 1
|
|
else
|
|
log "APPROVED: $fname (${new_size}B) $WARNINGS"
|
|
|
|
# Auto-backup current live before deploy
|
|
target_file="$TARGET/$fname"
|
|
if [ -f "$target_file" ]; then
|
|
cp "$target_file" "$target_file.bak-$(date +%Y%m%d%H%M%S)" 2>/dev/null
|
|
fi
|
|
|
|
echo '{"ok":true,"file":"'"$fname"'","size":'"$new_size"',"warnings":"'"$WARNINGS"'"}'
|
|
exit 0
|
|
fi
|