site/hook.sh

184 lines
6.2 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# Colors
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
echo -e "${GREEN}Running pre-push checks...${NC}"
# Paths
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
CONTENT_DIR="$REPO_ROOT/core/content"
MKDOCS_CFG_PATH="$CONTENT_DIR/mkdocs.yml"
SITE_DIR="$REPO_ROOT/site"
LOG_DIR="$REPO_ROOT/test/log"
# Clean logs
rm -rf "$LOG_DIR"; mkdir -p "$LOG_DIR"
SERVER_PID=""
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
# --- Optional lightweight checks (keep or remove) ---
if command -v trivy &>/dev/null; then
echo -e "${GREEN}Running Trivy scan...${NC}"
trivy fs . --exit-code 1 --severity CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN --no-progress \
>"$LOG_DIR/trivy.log" 2>&1 || { echo -e "${RED}Trivy failed. See $LOG_DIR/trivy.log${NC}"; exit 1; }
else
echo -e "${YELLOW}Trivy not installed. Skipping vulnerability scan.${NC}"
fi
if command -v trufflehog &>/dev/null && command -v jq &>/dev/null; then
echo -e "${GREEN}Running TruffleHog (verified only)...${NC}"
TMPF="$(mktemp)"
trufflehog filesystem . --json >"$TMPF" 2>"$LOG_DIR/trufflehog.log" || true
VERIFIED="$(jq 'select(.verified==true)' "$TMPF" | wc -l | tr -d ' ')"
if [[ "$VERIFIED" -gt 0 ]]; then
cp "$TMPF" "$LOG_DIR/trufflehog-findings.json"
echo -e "${RED}Verified secrets found. See $LOG_DIR/trufflehog-findings.json${NC}"
rm -f "$TMPF"; exit 1
fi
rm -f "$TMPF"
else
echo -e "${YELLOW}TruffleHog or jq not installed. Skipping secrets scan.${NC}"
fi
if command -v markdownlint &>/dev/null; then
echo -e "${GREEN}Running markdownlint...${NC}"
MD_FILES="$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$' || true)"
if [[ -n "$MD_FILES" ]]; then
# shellcheck disable=SC2086
echo $MD_FILES | xargs markdownlint >"$LOG_DIR/markdownlint.log" 2>&1 || {
echo -e "${RED}markdownlint failed. See $LOG_DIR/markdownlint.log${NC}"; exit 1; }
fi
else
echo -e "${YELLOW}markdownlint not installed. Skipping markdown check.${NC}"
fi
if command -v vale &>/dev/null && [[ -f "$REPO_ROOT/.vale.ini" ]]; then
echo -e "${GREEN}Running Vale...${NC}"
VALE_FILES="$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.md$' || true)"
if [[ -n "$VALE_FILES" ]]; then
# shellcheck disable=SC2086
echo $VALE_FILES | xargs vale >"$LOG_DIR/vale.log" 2>&1 || {
echo -e "${RED}Vale issues. See $LOG_DIR/vale.log${NC}"; exit 1; }
fi
else
echo -e "${YELLOW}Vale not installed or .vale.ini missing. Skipping Vale.${NC}"
fi
# --- MkDocs build (strict) ---
if ! command -v mkdocs >/dev/null 2>&1; then
echo -e "${RED}MkDocs not installed; cannot build docs.${NC}"; exit 1
fi
echo -e "${GREEN}Building documentation (strict)…${NC}"
mkdocs build -f "$MKDOCS_CFG_PATH" -d "$SITE_DIR" --strict >"$LOG_DIR/mkdocs-build.log" 2>&1 || {
echo -e "${RED}MkDocs build failed. See $LOG_DIR/mkdocs-build.log${NC}"; exit 1; }
# --- Serve built site ---
# if ! command -v python3 >/dev/null 2>&1; then
# echo -e "${RED}python3 not found; cannot serve static site.${NC}"; exit 1
# fi
# PORT="$(python3 - <<'PY'
# import socket
# s=socket.socket(); s.bind(('127.0.0.1',0))
# print(s.getsockname()[1]); s.close()
# PY
# )"
# STATIC_LOG="$LOG_DIR/static-serve.log"
# echo -e "${GREEN}Serving built site at http://127.0.0.1:$PORT …${NC}"
# python3 -m http.server "$PORT" --bind 127.0.0.1 --directory "$SITE_DIR" >"$STATIC_LOG" 2>&1 &
# SERVER_PID="$!"
# Wait for server
# echo -e "${GREEN}Waiting for local server to be reachable…${NC}"
# START_TIME="$(date +%s)"; TIMEOUT=60
# while : ; do
# if ! ps -p "$SERVER_PID" >/dev/null 2>&1; then
# echo -e "${RED}Static server died during startup. See $STATIC_LOG${NC}"; exit 1
# fi
# if curl --fail --silent -I "http://127.0.0.1:$PORT/" >/dev/null 2>>"$STATIC_LOG"; then break; fi
# if (( $(date +%s) - START_TIME >= TIMEOUT )); then
# echo -e "${RED}Static server did not come up in ${TIMEOUT}s.${NC}"
# tail -n 50 "$STATIC_LOG" || true; exit 1
# fi
# sleep 0.5
# done
# --- Build URL list (all *.html pages) ---
# URLS_FILE="$LOG_DIR/urls.txt"
# BASE_URL="http://127.0.0.1:$PORT/"
# export SITE_DIR BASE_URL
# python3 - <<'PY' > "$URLS_FILE"
# import os
# site = os.environ['SITE_DIR']; base = os.environ['BASE_URL']
# urls = []
# for root, _, files in os.walk(site):
# for name in files:
# if name.endswith('.html'):
# rel = os.path.relpath(os.path.join(root, name), site).replace(os.sep, '/')
# urls.append(base + rel)
# for u in sorted(urls): print(u)
# PY
# TOTAL="$(wc -l < "$URLS_FILE" | tr -d ' ')"
# echo -e "${GREEN}Lychee will scan ${TOTAL} pages…${NC}"
# # --- Lychee (single run, unbuffered, higher FD limit) ---
# if ! command -v lychee >/dev/null 2>&1; then
# echo -e "${YELLOW}Lychee not installed. Skipping link check.${NC}"
# cleanup; exit 0
# fi
# # Raise macOS open-file limit (best-effort) to avoid mid-run aborts
# ulimit -n 4096 || true
# CSV_OUT="$LOG_DIR/lychee.csv"
# RUN_LOG="$LOG_DIR/lychee-run.log"
# echo -e "${GREEN}Starting Lychee…${NC}"
# set +e
# # Use script(1) to allocate a PTY so output is line-buffered; tee to file.
# # Capture Lychee's real exit code via PIPESTATUS.
# script -q /dev/null lychee \
# --base-url "http://127.0.0.1:$PORT/" \
# --format detailed \
# --output "$CSV_OUT" \
# --verbose \
# --no-progress \
# --max-concurrency 16 \
# --timeout 30 \
# --max-retries 2 \
# --retry-wait-time 2 \
# --accept '100..=103,200..=399' \
# --exclude 'https?://(www\.)?github\.com/spread-ai' \
# --exclude 'https?://[^/]*app\.spread\.ai' \
# --exclude 'https?://[^/]*stage\.spread\.ai' \
# --exclude '\?q=' \
# --exclude '#__.*_annotation_.*' \
# - < "$URLS_FILE" 2>&1 | tee "$RUN_LOG"
# LYCHEE_RC=${PIPESTATUS[1]}
# set -e
# Stop server
# cleanup
# # Summarize and exit appropriately
# if [[ "$LYCHEE_RC" -ne 0 ]]; then
# echo -e "${RED}Lychee reported problems (exit $LYCHEE_RC). See:${NC}"
# echo " - $RUN_LOG"
# echo " - $CSV_OUT"
# echo " - $STATIC_LOG"
# exit 1
# else
# echo -e "${GREEN}Lychee completed successfully. See $CSV_OUT${NC}"
# fi