#!/bin/bash # Pre-push hook for Portfolio # Runs CI/CD checks before allowing push set -e echo "🚀 Running pre-push checks..." # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Function to print colored output print_status() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Check if we're in the right directory if [ ! -f "package.json" ]; then print_error "Not in project root directory!" exit 1 fi # Check if Node.js is available if ! command -v node &> /dev/null; then print_error "Node.js is not installed!" exit 1 fi # Check Node.js version NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1) if [ "$NODE_VERSION" -lt 20 ]; then print_error "Node.js version 20+ required, found: $(node --version)" exit 1 fi print_success "Node.js version: $(node --version)" # Install dependencies if node_modules doesn't exist if [ ! -d "node_modules" ]; then print_status "Installing dependencies..." npm ci else print_status "Dependencies already installed" fi # Run linting print_status "Running ESLint..." if npm run lint; then print_success "Linting passed" else print_error "Linting failed! Please fix the issues before pushing." exit 1 fi # Run tests print_status "Running tests..." if npm run test:production; then print_success "Tests passed" else print_error "Tests failed! Please fix the issues before pushing." exit 1 fi # Build application print_status "Building application..." if npm run build; then print_success "Build successful" else print_error "Build failed! Please fix the issues before pushing." exit 1 fi # Security audit print_status "Running security audit..." if npm audit --audit-level=high; then print_success "Security audit passed" else print_warning "Security audit found issues. Consider running 'npm audit fix'" # Don't fail the push for security warnings, just warn fi # Check for secrets in code print_status "Checking for secrets in code..." if [ -f "scripts/check-secrets.sh" ]; then chmod +x scripts/check-secrets.sh if ./scripts/check-secrets.sh; then print_success "No secrets found in code" else print_error "Secrets detected in code! Please remove them before pushing." exit 1 fi else print_warning "Secret check script not found, skipping..." fi # Check Docker configuration print_status "Checking Docker configuration..." if [ -f "Dockerfile" ]; then print_success "Dockerfile found" else print_error "Dockerfile not found!" exit 1 fi if [ -f "docker-compose.yml" ]; then print_success "Docker Compose configuration found" else print_error "Docker Compose configuration not found!" exit 1 fi # Check if we're pushing to production branch CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) if [ "$CURRENT_BRANCH" = "production" ]; then print_warning "Pushing to production branch - this will trigger deployment!" # Additional production checks print_status "Running production-specific checks..." # Check if environment file exists if [ ! -f ".env" ]; then print_warning "No .env file found. Make sure secrets are configured in Gitea." fi # Check if Docker is running and ready print_status "Checking Docker status..." if ! docker info > /dev/null 2>&1; then print_error "Docker is not running! Please start Docker before pushing." print_status "To start Docker:" print_status " - macOS: Open Docker Desktop application" print_status " - Linux: sudo systemctl start docker" print_status " - Windows: Start Docker Desktop application" print_status "" print_status "Wait for Docker to fully start before trying again." exit 1 fi # Test Docker functionality if ! docker run --rm hello-world > /dev/null 2>&1; then print_error "Docker is running but not functional!" print_status "Docker might still be starting up. Please wait and try again." print_status "Or restart Docker if the issue persists." exit 1 fi print_success "Docker is running and functional" # Check Docker image can be built print_status "Testing Docker build..." # Create a temporary log file for build output BUILD_LOG=$(mktemp) if docker build -t portfolio-app:test . > "$BUILD_LOG" 2>&1; then print_success "Docker build test passed" docker rmi portfolio-app:test > /dev/null 2>&1 rm -f "$BUILD_LOG" else print_error "Docker build test failed!" print_status "Build errors:" echo "----------------------------------------" cat "$BUILD_LOG" echo "----------------------------------------" print_status "Please fix Docker build issues before pushing." print_status "Common issues:" print_status " - Missing files referenced in Dockerfile" print_status " - Network issues during npm install" print_status " - Insufficient disk space" rm -f "$BUILD_LOG" exit 1 fi fi # Final success message echo "" print_success "All pre-push checks passed! ✅" print_status "Ready to push to: $CURRENT_BRANCH" # Show what will be pushed echo "" print_status "Files to be pushed:" git diff --name-only HEAD~1 2>/dev/null || git diff --cached --name-only echo "" print_success "🚀 Push will proceed..."