268 lines
6.9 KiB
Bash
Executable File
268 lines
6.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Installation script for Git hooks in Hastebin
|
|
# This script sets up pre-commit hooks (tests + security scan) and pre-push hooks (unused code + security scan)
|
|
#
|
|
# Usage:
|
|
# ./install-git-hooks.sh [--force]
|
|
#
|
|
# Options:
|
|
# --force Overwrite existing hooks without prompting (backs up existing hooks)
|
|
# Without this flag, fails if hooks already exist
|
|
|
|
set -e
|
|
|
|
# Parse arguments
|
|
FORCE_MODE=false
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--force)
|
|
FORCE_MODE=true
|
|
shift
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
echo "Usage: $0 [--force]"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Get the repository root
|
|
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)")
|
|
HOOKS_DIR="$REPO_ROOT/.git/hooks"
|
|
PRE_COMMIT_HOOK="$HOOKS_DIR/pre-commit"
|
|
PRE_PUSH_HOOK="$HOOKS_DIR/pre-push"
|
|
SCRIPT_DIR="$REPO_ROOT/scripts"
|
|
|
|
echo -e "${BLUE}Installing Git hooks for Hastebin${NC}"
|
|
echo ""
|
|
|
|
# Check if we're in a git repository
|
|
if [ ! -d "$REPO_ROOT/.git" ]; then
|
|
echo -e "${RED}Error: Not a git repository${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Create hooks directory if it doesn't exist
|
|
mkdir -p "$HOOKS_DIR"
|
|
|
|
# Function to handle existing hook
|
|
handle_existing_hook() {
|
|
local hook_path="$1"
|
|
local hook_name="$2"
|
|
|
|
if [ -f "$hook_path" ]; then
|
|
if [ "$FORCE_MODE" = true ]; then
|
|
# Backup existing hook with timestamp
|
|
mv "$hook_path" "$hook_path.backup.$(date +%Y%m%d_%H%M%S)"
|
|
echo -e "${YELLOW}Backed up existing $hook_name hook${NC}"
|
|
else
|
|
echo -e "${RED}Error: $hook_name hook already exists at $hook_path${NC}"
|
|
echo -e "${YELLOW}Use --force to overwrite (will backup existing hook)${NC}"
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Check for existing hooks
|
|
handle_existing_hook "$PRE_COMMIT_HOOK" "pre-commit"
|
|
handle_existing_hook "$PRE_PUSH_HOOK" "pre-push"
|
|
|
|
# --- Create the pre-commit hook ---
|
|
cat > "$PRE_COMMIT_HOOK" << 'HOOK_EOF'
|
|
#!/bin/bash
|
|
|
|
# Git pre-commit hook for Hastebin
|
|
# Runs tests and security scans before allowing commits
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo -e "${YELLOW}Running pre-commit checks...${NC}"
|
|
echo ""
|
|
|
|
# Get the repository root
|
|
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
cd "$REPO_ROOT"
|
|
|
|
# Check required dependencies
|
|
MISSING_DEPS=0
|
|
|
|
if ! command -v docker &> /dev/null; then
|
|
echo -e "${RED}Docker not found - required for security scanning${NC}"
|
|
MISSING_DEPS=1
|
|
fi
|
|
|
|
if ! command -v trivy &> /dev/null; then
|
|
echo -e "${RED}Trivy not found - required for security scanning${NC}"
|
|
echo " Install: brew install trivy"
|
|
MISSING_DEPS=1
|
|
fi
|
|
|
|
if [ $MISSING_DEPS -ne 0 ]; then
|
|
echo -e "${RED}Missing required dependencies. Commit aborted.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if node_modules exists, if not, install dependencies
|
|
if [ ! -d "node_modules" ]; then
|
|
echo -e "${YELLOW}Installing dependencies...${NC}"
|
|
npm ci
|
|
fi
|
|
|
|
# Run the core tests (faster than full test suite)
|
|
echo -e "${YELLOW}[1/2] Running core tests...${NC}"
|
|
if npm run test:core; then
|
|
echo -e "${GREEN}Core tests passed${NC}"
|
|
else
|
|
echo -e "${RED}Core tests failed. Commit aborted.${NC}"
|
|
echo -e "${YELLOW}To skip this check, use: git commit --no-verify${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Clean up test artifacts
|
|
if [ -d "test-data" ]; then
|
|
rm -rf test-data
|
|
fi
|
|
|
|
# Run Trivy security scan
|
|
echo ""
|
|
echo -e "${YELLOW}[2/2] Running security scan (Trivy image scan)...${NC}"
|
|
if "$REPO_ROOT/scripts/scan-trivy-image.sh"; then
|
|
echo -e "${GREEN}Security scan passed${NC}"
|
|
else
|
|
echo -e "${RED}Security scan found vulnerabilities. Commit aborted.${NC}"
|
|
echo -e "${YELLOW}To skip this check, use: git commit --no-verify${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${GREEN}Pre-commit checks passed${NC}"
|
|
exit 0
|
|
HOOK_EOF
|
|
|
|
chmod +x "$PRE_COMMIT_HOOK"
|
|
echo -e "${GREEN}Pre-commit hook installed${NC}"
|
|
|
|
# --- Create the pre-push hook ---
|
|
cat > "$PRE_PUSH_HOOK" << 'HOOK_EOF'
|
|
#!/bin/bash
|
|
|
|
# Git pre-push hook for Hastebin
|
|
# Scans for unused code/dependencies and runs security scan before pushing
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo -e "${YELLOW}Running pre-push checks...${NC}"
|
|
echo ""
|
|
|
|
# Get the repository root
|
|
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
cd "$REPO_ROOT"
|
|
|
|
# Check required dependencies
|
|
MISSING_DEPS=0
|
|
|
|
if ! command -v docker &> /dev/null; then
|
|
echo -e "${RED}Docker not found - required for security scanning${NC}"
|
|
MISSING_DEPS=1
|
|
fi
|
|
|
|
if ! command -v trivy &> /dev/null; then
|
|
echo -e "${RED}Trivy not found - required for security scanning${NC}"
|
|
echo " Install: brew install trivy"
|
|
MISSING_DEPS=1
|
|
fi
|
|
|
|
if [ $MISSING_DEPS -ne 0 ]; then
|
|
echo -e "${RED}Missing required dependencies. Push aborted.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if node_modules exists, if not, install dependencies
|
|
if [ ! -d "node_modules" ]; then
|
|
echo -e "${YELLOW}Installing dependencies...${NC}"
|
|
npm ci
|
|
fi
|
|
|
|
# Scan for unused code/dependencies
|
|
SCAN_FAILED=0
|
|
|
|
echo -e "${YELLOW}[1/3] Scanning for unused files/exports/dependencies (knip)...${NC}"
|
|
if npx --yes knip 2>/dev/null; then
|
|
echo -e "${GREEN}knip passed${NC}"
|
|
else
|
|
echo -e "${RED}knip found unused code${NC}"
|
|
SCAN_FAILED=1
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${YELLOW}[2/3] Scanning for unused npm dependencies (depcheck)...${NC}"
|
|
if npx --yes depcheck 2>/dev/null; then
|
|
echo -e "${GREEN}depcheck passed${NC}"
|
|
else
|
|
echo -e "${RED}depcheck found issues${NC}"
|
|
SCAN_FAILED=1
|
|
fi
|
|
|
|
if [ $SCAN_FAILED -ne 0 ]; then
|
|
echo -e "${RED}Unused code/dependencies detected. Push aborted.${NC}"
|
|
echo -e "${YELLOW}To skip this check, use: git push --no-verify${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Run Trivy security scan
|
|
echo ""
|
|
echo -e "${YELLOW}[3/3] Running security scan (Trivy image scan)...${NC}"
|
|
if "$REPO_ROOT/scripts/scan-trivy-image.sh"; then
|
|
echo -e "${GREEN}Security scan passed${NC}"
|
|
else
|
|
echo -e "${RED}Security scan found vulnerabilities. Push aborted.${NC}"
|
|
echo -e "${YELLOW}To skip this check, use: git push --no-verify${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${GREEN}Pre-push checks passed${NC}"
|
|
exit 0
|
|
HOOK_EOF
|
|
|
|
chmod +x "$PRE_PUSH_HOOK"
|
|
echo -e "${GREEN}Pre-push hook installed${NC}"
|
|
|
|
echo ""
|
|
echo -e "${BLUE}Hooks installed:${NC}"
|
|
echo -e "${BLUE} - pre-commit: core tests + Trivy security scan${NC}"
|
|
echo -e "${BLUE} - pre-push: knip + depcheck + Trivy security scan${NC}"
|
|
echo -e "${YELLOW}To skip hooks, use: git commit --no-verify / git push --no-verify${NC}"
|
|
echo ""
|
|
|
|
# Check if dependencies are installed
|
|
if [ ! -d "$REPO_ROOT/node_modules" ]; then
|
|
echo -e "${YELLOW}Dependencies not found. Installing...${NC}"
|
|
cd "$REPO_ROOT"
|
|
npm ci
|
|
echo -e "${GREEN}Dependencies installed${NC}"
|
|
fi
|
|
|
|
echo -e "${GREEN}Git hooks installation complete!${NC}"
|