#!/usr/bin/env bash # Pre-push hook for comprehensive repository checks # Fail fast on any error set -euo pipefail # Color codes readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' readonly YELLOW='\033[1;33m' readonly NC='\033[0m' # Paths readonly REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" readonly CONTENT_DIR="${REPO_ROOT}/content" readonly ZENSICAL_CFG_PATH="${REPO_ROOT}/zensical.toml" readonly SITE_DIR="${REPO_ROOT}/deploy" readonly LOG_DIR="${REPO_ROOT}/logs" # Logging and error handling log_error() { echo -e "${RED}[ERROR] $*${NC}" >&2 } log_info() { echo -e "${GREEN}[INFO] $*${NC}" } log_warning() { echo -e "${YELLOW}[WARNING] $*${NC}" } # Cleanup function cleanup() { if [[ -n "${SERVER_PID:-}" ]] && ps -p "$SERVER_PID" >/dev/null 2>&1; then kill "$SERVER_PID" >/dev/null 2>&1 || true for _ in {1..30}; do ps -p "$SERVER_PID" >/dev/null 2>&1 || break sleep 0.1 done fi } trap cleanup EXIT INT TERM # Initialize log directory prepare_log_directory() { rm -rf "$LOG_DIR" mkdir -p "$LOG_DIR" } # Vulnerability Scanning run_trivy_scan() { if ! command -v trivy &>/dev/null; then log_warning "Trivy not installed. Skipping vulnerability scan." return 0 fi log_info "Running Trivy scan..." trivy fs . \ --exit-code 1 \ --severity CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN \ --no-progress \ >"$LOG_DIR/trivy.log" 2>&1 || { log_error "Trivy failed. See $LOG_DIR/trivy.log" return 1 } } # Secrets Detection run_trufflehog_scan() { if ! (command -v trufflehog &>/dev/null && command -v jq &>/dev/null); then log_warning "TruffleHog or jq not installed. Skipping secrets scan." return 0 fi log_info "Running TruffleHog (verified only)..." local tmpf tmpf="$(mktemp)" trufflehog filesystem . --json >"$tmpf" 2>"$LOG_DIR/trufflehog.log" || true local verified verified="$(jq 'select(.verified==true)' "$tmpf" | wc -l | tr -d ' ')" if [[ "$verified" -gt 0 ]]; then cp "$tmpf" "$LOG_DIR/trufflehog-findings.json" log_error "Verified secrets found. See $LOG_DIR/trufflehog-findings.json" rm -f "$tmpf" return 1 fi rm -f "$tmpf" } # Additional security and lint checks run_additional_checks() { # Git Secrets if command -v git-secrets &>/dev/null; then log_info "Running git-secrets scan..." git-secrets --scan >"$LOG_DIR/git-secrets.log" 2>&1 || { log_error "git-secrets detected potential secrets. See $LOG_DIR/git-secrets.log" return 1 } fi # Python Security (Bandit) if command -v bandit &>/dev/null; then log_info "Running Bandit Python security scan..." local py_files py_files="$(find . -type f -name "*.py")" if [[ -n "$py_files" ]]; then # shellcheck disable=SC2086 bandit -r $py_files -n 5 -lll -f json -o "$LOG_DIR/bandit.json" 2>"$LOG_DIR/bandit.log" || { log_error "Bandit issues found. See $LOG_DIR/bandit.log" return 1 } fi fi # Dependabot-like checks if command -v npm &>/dev/null && [[ -f package.json ]]; then log_info "Running npm audit..." npm audit --audit-level=high >"$LOG_DIR/npm-audit.log" 2>&1 || { log_error "npm audit found issues. See $LOG_DIR/npm-audit.log" return 1 } fi # Stylelint if command -v stylelint &>/dev/null; then log_info "Running Stylelint..." stylelint "**/*.{css,scss}" --formatter json >"$LOG_DIR/stylelint.json" 2>"$LOG_DIR/stylelint.log" || { log_error "Stylelint issues found. See $LOG_DIR/stylelint.log" return 1 } fi } # Main execution main() { prepare_log_directory run_trivy_scan run_trufflehog_scan run_additional_checks log_info "All pre-push checks passed successfully!" } # Run the main function main "$@"