736 lines
17 KiB
Markdown
736 lines
17 KiB
Markdown
# Git Hooks and Validation Scripts Guide
|
|
|
|
This guide provides comprehensive examples and guidelines for git hooks and validation scripts used in GitLab Stack projects.
|
|
|
|
## Overview
|
|
|
|
Git hooks are scripts that run automatically at specific points in the git workflow. For GitLab Stack projects, we use hooks to ensure validation before commits.
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
project-name/
|
|
├── .git/
|
|
│ └── hooks/
|
|
│ └── pre-commit # Installed hook
|
|
└── scripts/
|
|
├── pre-commit # Source hook script
|
|
├── validate-stack.sh # Full validation
|
|
└── setup-hooks.sh # Hook installer
|
|
```
|
|
|
|
## Core Scripts
|
|
|
|
### 1. scripts/pre-commit
|
|
|
|
The pre-commit hook runs before each commit to validate the stack.
|
|
|
|
**Location**: `scripts/pre-commit`
|
|
**Installed to**: `.git/hooks/pre-commit`
|
|
**When it runs**: Before `git commit`
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
#
|
|
# Pre-commit hook for GitLab Stack validation
|
|
# Prevents commits that violate stack patterns
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo "========================================="
|
|
echo "Pre-commit validation"
|
|
echo "========================================="
|
|
echo
|
|
|
|
ERRORS=0
|
|
|
|
# Check 1: Secrets in staged files
|
|
echo "1. Checking for secrets in staged files..."
|
|
if git diff --cached --name-only | grep -qE "secrets/.*[^.gitkeep]|\.env$"; then
|
|
echo -e "${RED}✗ ERROR: Attempting to commit secrets or .env file!${NC}"
|
|
echo " Secrets should NEVER be committed to git."
|
|
echo " Files detected:"
|
|
git diff --cached --name-only | grep -E "secrets/.*[^.gitkeep]|\.env$" | sed 's/^/ /'
|
|
((ERRORS++))
|
|
else
|
|
echo -e "${GREEN}✓ No secrets in staged files${NC}"
|
|
fi
|
|
echo
|
|
|
|
# Check 2: Root-owned files
|
|
echo "2. Checking for root-owned files..."
|
|
if find . -user root -not -path "./.git/*" 2>/dev/null | grep -q .; then
|
|
echo -e "${RED}✗ ERROR: Root-owned files detected!${NC}"
|
|
echo " All files should be owned by the user running Docker."
|
|
echo " Files detected:"
|
|
find . -user root -not -path "./.git/*" 2>/dev/null | sed 's/^/ /'
|
|
echo
|
|
echo " Fix with: sudo chown -R \$USER:\$USER ."
|
|
((ERRORS++))
|
|
else
|
|
echo -e "${GREEN}✓ No root-owned files${NC}"
|
|
fi
|
|
echo
|
|
|
|
# Check 3: Secrets in file content (basic check)
|
|
echo "3. Checking for hardcoded secrets in code..."
|
|
SUSPICIOUS_PATTERNS=(
|
|
"password\s*=\s*['\"][^'\"]+['\"]"
|
|
"api[_-]?key\s*=\s*['\"][^'\"]+['\"]"
|
|
"secret\s*=\s*['\"][^'\"]+['\"]"
|
|
"token\s*=\s*['\"][^'\"]+['\"]"
|
|
)
|
|
|
|
FOUND_SECRETS=false
|
|
for pattern in "${SUSPICIOUS_PATTERNS[@]}"; do
|
|
if git diff --cached | grep -iE "$pattern" | grep -v "\.example" | grep -q .; then
|
|
if [ "$FOUND_SECRETS" = false ]; then
|
|
echo -e "${YELLOW}⚠ WARNING: Possible hardcoded secrets detected:${NC}"
|
|
FOUND_SECRETS=true
|
|
fi
|
|
git diff --cached | grep -iE "$pattern" | grep -v "\.example" | sed 's/^/ /'
|
|
fi
|
|
done
|
|
|
|
if [ "$FOUND_SECRETS" = true ]; then
|
|
echo
|
|
echo " Review these carefully. Use environment variables or Docker secrets instead."
|
|
echo " If these are false positives, you can proceed."
|
|
else
|
|
echo -e "${GREEN}✓ No obvious hardcoded secrets${NC}"
|
|
fi
|
|
echo
|
|
|
|
# Check 4: Full stack validation (if available)
|
|
if [ -x "./scripts/validate-stack.sh" ]; then
|
|
echo "4. Running full stack validation..."
|
|
if ! ./scripts/validate-stack.sh; then
|
|
echo -e "${RED}✗ ERROR: Stack validation failed!${NC}"
|
|
echo " Fix all issues before committing."
|
|
echo " Or use 'git commit --no-verify' to skip (NOT recommended)."
|
|
((ERRORS++))
|
|
else
|
|
echo -e "${GREEN}✓ Stack validation passed${NC}"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Skipping stack validation (./scripts/validate-stack.sh not found)${NC}"
|
|
fi
|
|
echo
|
|
|
|
# Final result
|
|
echo "========================================="
|
|
if [ $ERRORS -gt 0 ]; then
|
|
echo -e "${RED}Pre-commit validation FAILED with $ERRORS error(s)${NC}"
|
|
echo "========================================="
|
|
echo
|
|
echo "To skip this validation (NOT recommended):"
|
|
echo " git commit --no-verify"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}Pre-commit validation PASSED!${NC}"
|
|
echo "========================================="
|
|
exit 0
|
|
```
|
|
|
|
**Usage**:
|
|
```bash
|
|
# Automatic - runs on every commit
|
|
git commit -m "message"
|
|
|
|
# Skip validation (emergency only)
|
|
git commit --no-verify -m "message"
|
|
```
|
|
|
|
---
|
|
|
|
### 2. scripts/validate-stack.sh
|
|
|
|
Comprehensive validation script that runs all validators.
|
|
|
|
**Location**: `scripts/validate-stack.sh`
|
|
**When to run**: Before deployment, in CI/CD, or manually
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
#
|
|
# Full GitLab Stack validation
|
|
# Runs all validators to ensure stack compliance
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo
|
|
echo -e "${BLUE}========================================"
|
|
echo "GitLab Stack Validation"
|
|
echo "========================================${NC}"
|
|
echo
|
|
|
|
ERRORS=0
|
|
WARNINGS=0
|
|
|
|
# Check if we're in a stack directory
|
|
if [ ! -f "docker-compose.yml" ]; then
|
|
echo -e "${RED}✗ ERROR: docker-compose.yml not found!${NC}"
|
|
echo " Are you in a stack directory?"
|
|
exit 1
|
|
fi
|
|
|
|
# Validation 1: Stack Validator
|
|
echo -e "${BLUE}[1/4] Running stack-validator...${NC}"
|
|
if command -v claude-code >/dev/null 2>&1; then
|
|
if claude-code run stack-validator 2>&1 | tee /tmp/stack-validator.log; then
|
|
echo -e "${GREEN}✓ Stack validation passed${NC}"
|
|
else
|
|
echo -e "${RED}✗ Stack validation failed${NC}"
|
|
echo " Review output above for details"
|
|
((ERRORS++))
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Claude Code not available, skipping stack-validator${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
echo
|
|
|
|
# Validation 2: Secrets Manager
|
|
echo -e "${BLUE}[2/4] Running secrets-manager validation...${NC}"
|
|
if command -v claude-code >/dev/null 2>&1; then
|
|
if claude-code run secrets-manager --validate 2>&1 | tee /tmp/secrets-manager.log; then
|
|
echo -e "${GREEN}✓ Secrets validation passed${NC}"
|
|
else
|
|
echo -e "${RED}✗ Secrets validation failed${NC}"
|
|
echo " Review output above for details"
|
|
((ERRORS++))
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Claude Code not available, running basic secrets check${NC}"
|
|
|
|
# Basic secrets check without Claude Code
|
|
if find secrets/ -type f ! -name ".gitkeep" 2>/dev/null | grep -q .; then
|
|
if grep -r "DOCKER_SECRET" docker-compose.yml >/dev/null 2>&1; then
|
|
echo -e "${GREEN}✓ Basic secrets check passed${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Secrets files found but not referenced in docker-compose.yml${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
else
|
|
echo -e "${GREEN}✓ No secrets configured${NC}"
|
|
fi
|
|
fi
|
|
echo
|
|
|
|
# Validation 3: Docker Validator
|
|
echo -e "${BLUE}[3/4] Running docker-validation...${NC}"
|
|
if command -v claude-code >/dev/null 2>&1; then
|
|
if claude-code run docker-validation 2>&1 | tee /tmp/docker-validation.log; then
|
|
echo -e "${GREEN}✓ Docker validation passed${NC}"
|
|
else
|
|
echo -e "${RED}✗ Docker validation failed${NC}"
|
|
echo " Review output above for details"
|
|
((ERRORS++))
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Claude Code not available, running basic Docker checks${NC}"
|
|
|
|
# Basic docker-compose syntax check
|
|
if docker compose config >/dev/null 2>&1; then
|
|
echo -e "${GREEN}✓ docker-compose.yml syntax valid${NC}"
|
|
else
|
|
echo -e "${RED}✗ docker-compose.yml syntax invalid${NC}"
|
|
((ERRORS++))
|
|
fi
|
|
fi
|
|
echo
|
|
|
|
# Validation 4: File Ownership
|
|
echo -e "${BLUE}[4/4] Checking file ownership...${NC}"
|
|
if find . -user root -not -path "./.git/*" 2>/dev/null | grep -q .; then
|
|
echo -e "${RED}✗ Root-owned files detected:${NC}"
|
|
find . -user root -not -path "./.git/*" 2>/dev/null | sed 's/^/ /'
|
|
echo
|
|
echo " Fix with: sudo chown -R \$USER:\$USER ."
|
|
((ERRORS++))
|
|
else
|
|
echo -e "${GREEN}✓ No root-owned files${NC}"
|
|
fi
|
|
echo
|
|
|
|
# Additional checks
|
|
echo -e "${BLUE}Additional checks:${NC}"
|
|
|
|
# Check .env vs .env.example sync
|
|
if [ -f ".env.example" ]; then
|
|
ENV_KEYS=$(grep -v '^#' .env.example 2>/dev/null | grep '=' | cut -d= -f1 | sort)
|
|
if [ -f ".env" ]; then
|
|
ACTUAL_KEYS=$(grep -v '^#' .env 2>/dev/null | grep '=' | cut -d= -f1 | sort)
|
|
if [ "$ENV_KEYS" != "$ACTUAL_KEYS" ]; then
|
|
echo -e "${YELLOW}⚠ .env and .env.example keys don't match${NC}"
|
|
((WARNINGS++))
|
|
else
|
|
echo -e "${GREEN}✓ .env synced with .env.example${NC}"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ .env file not found (expected from .env.example)${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
fi
|
|
|
|
# Check git setup
|
|
if [ -d ".git" ]; then
|
|
# Check default branch
|
|
DEFAULT_BRANCH=$(git config init.defaultBranch 2>/dev/null || echo "")
|
|
if [ "$DEFAULT_BRANCH" = "main" ]; then
|
|
echo -e "${GREEN}✓ Git default branch: main${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Git default branch not set to 'main'${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
|
|
# Check merge strategy
|
|
MERGE_FF=$(git config merge.ff 2>/dev/null || echo "")
|
|
if [ "$MERGE_FF" = "only" ]; then
|
|
echo -e "${GREEN}✓ Git merge strategy: ff-only${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Git merge strategy not set to 'ff-only'${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ Not a git repository${NC}"
|
|
((WARNINGS++))
|
|
fi
|
|
|
|
echo
|
|
|
|
# Final report
|
|
echo -e "${BLUE}========================================"
|
|
echo "Validation Summary"
|
|
echo "========================================${NC}"
|
|
|
|
if [ $ERRORS -gt 0 ]; then
|
|
echo -e "${RED}FAILED: $ERRORS error(s) found${NC}"
|
|
if [ $WARNINGS -gt 0 ]; then
|
|
echo -e "${YELLOW}$WARNINGS warning(s) found${NC}"
|
|
fi
|
|
echo "========================================${NC}"
|
|
exit 1
|
|
elif [ $WARNINGS -gt 0 ]; then
|
|
echo -e "${YELLOW}PASSED with $WARNINGS warning(s)${NC}"
|
|
echo "========================================${NC}"
|
|
exit 0
|
|
else
|
|
echo -e "${GREEN}ALL VALIDATIONS PASSED!${NC}"
|
|
echo "========================================${NC}"
|
|
exit 0
|
|
fi
|
|
```
|
|
|
|
**Usage**:
|
|
```bash
|
|
# Run full validation
|
|
./scripts/validate-stack.sh
|
|
|
|
# In CI/CD
|
|
./scripts/validate-stack.sh || exit 1
|
|
```
|
|
|
|
---
|
|
|
|
### 3. scripts/setup-hooks.sh
|
|
|
|
Script to install git hooks from scripts/ to .git/hooks/
|
|
|
|
**Location**: `scripts/setup-hooks.sh`
|
|
**When to run**: After cloning, during stack creation
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
#
|
|
# Install git hooks from scripts/ to .git/hooks/
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors
|
|
GREEN='\033[0;32m'
|
|
RED='\033[0;31m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
echo "Installing git hooks..."
|
|
echo
|
|
|
|
# Check if .git exists
|
|
if [ ! -d ".git" ]; then
|
|
echo -e "${RED}✗ ERROR: Not a git repository!${NC}"
|
|
echo " Initialize git first: git init"
|
|
exit 1
|
|
fi
|
|
|
|
# Ensure hooks directory exists
|
|
mkdir -p .git/hooks
|
|
|
|
INSTALLED=0
|
|
FAILED=0
|
|
|
|
# Install pre-commit hook
|
|
if [ -f "scripts/pre-commit" ]; then
|
|
if cp scripts/pre-commit .git/hooks/pre-commit; then
|
|
chmod +x .git/hooks/pre-commit
|
|
echo -e "${GREEN}✓ Installed pre-commit hook${NC}"
|
|
((INSTALLED++))
|
|
else
|
|
echo -e "${RED}✗ Failed to install pre-commit hook${NC}"
|
|
((FAILED++))
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ scripts/pre-commit not found, skipping${NC}"
|
|
fi
|
|
|
|
# Install pre-push hook (if exists)
|
|
if [ -f "scripts/pre-push" ]; then
|
|
if cp scripts/pre-push .git/hooks/pre-push; then
|
|
chmod +x .git/hooks/pre-push
|
|
echo -e "${GREEN}✓ Installed pre-push hook${NC}"
|
|
((INSTALLED++))
|
|
else
|
|
echo -e "${RED}✗ Failed to install pre-push hook${NC}"
|
|
((FAILED++))
|
|
fi
|
|
fi
|
|
|
|
echo
|
|
echo "========================================="
|
|
if [ $FAILED -gt 0 ]; then
|
|
echo -e "${RED}Installation completed with $FAILED error(s)${NC}"
|
|
echo "========================================="
|
|
exit 1
|
|
elif [ $INSTALLED -eq 0 ]; then
|
|
echo -e "${YELLOW}No hooks installed${NC}"
|
|
echo "========================================="
|
|
exit 0
|
|
else
|
|
echo -e "${GREEN}Successfully installed $INSTALLED hook(s)!${NC}"
|
|
echo "========================================="
|
|
echo
|
|
echo "Hooks will now run automatically:"
|
|
echo " - pre-commit: Before each commit"
|
|
echo
|
|
echo "To skip hooks (emergency only):"
|
|
echo " git commit --no-verify"
|
|
fi
|
|
```
|
|
|
|
**Usage**:
|
|
```bash
|
|
# Install hooks
|
|
./scripts/setup-hooks.sh
|
|
|
|
# Verify installation
|
|
ls -la .git/hooks/
|
|
```
|
|
|
|
---
|
|
|
|
## Optional Hooks
|
|
|
|
### scripts/pre-push (Optional)
|
|
|
|
Runs before `git push` to ensure remote-ready state.
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
#
|
|
# Pre-push hook for GitLab Stack
|
|
# Runs before pushing to remote
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
echo "========================================="
|
|
echo "Pre-push validation"
|
|
echo "========================================="
|
|
echo
|
|
|
|
ERRORS=0
|
|
|
|
# Run full validation before push
|
|
echo "Running full stack validation..."
|
|
if [ -x "./scripts/validate-stack.sh" ]; then
|
|
if ! ./scripts/validate-stack.sh; then
|
|
echo -e "${RED}✗ Stack validation failed!${NC}"
|
|
echo " Fix issues before pushing."
|
|
((ERRORS++))
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}⚠ ./scripts/validate-stack.sh not found${NC}"
|
|
fi
|
|
|
|
# Check for uncommitted changes
|
|
if ! git diff-index --quiet HEAD --; then
|
|
echo -e "${YELLOW}⚠ WARNING: You have uncommitted changes${NC}"
|
|
echo " Consider committing them before pushing."
|
|
fi
|
|
|
|
echo
|
|
if [ $ERRORS -gt 0 ]; then
|
|
echo -e "${RED}Pre-push validation FAILED${NC}"
|
|
echo "To skip: git push --no-verify"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}Pre-push validation PASSED${NC}"
|
|
exit 0
|
|
```
|
|
|
|
---
|
|
|
|
## CI/CD Integration
|
|
|
|
### GitLab CI (.gitlab-ci.yml)
|
|
|
|
```yaml
|
|
stages:
|
|
- validate
|
|
- build
|
|
- deploy
|
|
|
|
validate:
|
|
stage: validate
|
|
image: docker:latest
|
|
services:
|
|
- docker:dind
|
|
before_script:
|
|
- apk add --no-cache bash findutils
|
|
script:
|
|
- chmod +x ./scripts/validate-stack.sh
|
|
- ./scripts/validate-stack.sh
|
|
only:
|
|
- merge_requests
|
|
- main
|
|
```
|
|
|
|
### GitHub Actions (.github/workflows/validate.yml)
|
|
|
|
```yaml
|
|
name: Stack Validation
|
|
|
|
on:
|
|
push:
|
|
branches: [ main ]
|
|
pull_request:
|
|
branches: [ main ]
|
|
|
|
jobs:
|
|
validate:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- name: Run stack validation
|
|
run: |
|
|
chmod +x ./scripts/validate-stack.sh
|
|
./scripts/validate-stack.sh
|
|
```
|
|
|
|
---
|
|
|
|
## Best Practices
|
|
|
|
### 1. Always Make Scripts Executable
|
|
|
|
```bash
|
|
chmod +x scripts/*.sh
|
|
chmod +x scripts/pre-commit
|
|
```
|
|
|
|
### 2. Test Hooks Before Committing
|
|
|
|
```bash
|
|
# Test pre-commit manually
|
|
./scripts/pre-commit
|
|
|
|
# Test validation
|
|
./scripts/validate-stack.sh
|
|
```
|
|
|
|
### 3. Document Hook Behavior
|
|
|
|
Include in README.md:
|
|
```markdown
|
|
## Git Hooks
|
|
|
|
This project uses git hooks for validation:
|
|
- **pre-commit**: Validates before each commit
|
|
- To skip: `git commit --no-verify` (emergency only)
|
|
```
|
|
|
|
### 4. Provide Skip Option
|
|
|
|
Always allow users to skip in emergencies:
|
|
```bash
|
|
git commit --no-verify -m "emergency fix"
|
|
```
|
|
|
|
### 5. Keep Hooks Fast
|
|
|
|
- Pre-commit should run in < 10 seconds
|
|
- Use quick checks when possible
|
|
- Defer expensive checks to CI/CD
|
|
|
|
### 6. Clear Error Messages
|
|
|
|
```bash
|
|
echo -e "${RED}✗ ERROR: Clear description${NC}"
|
|
echo " Explanation of what went wrong"
|
|
echo " How to fix it"
|
|
```
|
|
|
|
### 7. Exit Codes
|
|
|
|
```bash
|
|
# Success
|
|
exit 0
|
|
|
|
# Failure
|
|
exit 1
|
|
|
|
# Always use set -e to catch errors
|
|
set -euo pipefail
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Hook Not Running
|
|
|
|
```bash
|
|
# Check if hook is installed
|
|
ls -la .git/hooks/pre-commit
|
|
|
|
# Check if executable
|
|
chmod +x .git/hooks/pre-commit
|
|
|
|
# Reinstall hooks
|
|
./scripts/setup-hooks.sh
|
|
```
|
|
|
|
### Hook Fails Unexpectedly
|
|
|
|
```bash
|
|
# Run hook manually to see output
|
|
./scripts/pre-commit
|
|
|
|
# Check validation separately
|
|
./scripts/validate-stack.sh
|
|
|
|
# Debug with set -x
|
|
bash -x scripts/pre-commit
|
|
```
|
|
|
|
### Skip Hook Temporarily
|
|
|
|
```bash
|
|
# Skip pre-commit
|
|
git commit --no-verify -m "message"
|
|
|
|
# Skip pre-push
|
|
git push --no-verify
|
|
```
|
|
|
|
### Permission Denied
|
|
|
|
```bash
|
|
# Make script executable
|
|
chmod +x scripts/pre-commit
|
|
chmod +x scripts/validate-stack.sh
|
|
|
|
# Reinstall hooks
|
|
./scripts/setup-hooks.sh
|
|
```
|
|
|
|
---
|
|
|
|
## Customization
|
|
|
|
### Adding Custom Checks
|
|
|
|
Edit `scripts/pre-commit`:
|
|
|
|
```bash
|
|
# Add custom check
|
|
echo "5. Running custom validation..."
|
|
if ! ./scripts/my-custom-check.sh; then
|
|
echo -e "${RED}✗ Custom validation failed${NC}"
|
|
((ERRORS++))
|
|
else
|
|
echo -e "${GREEN}✓ Custom validation passed${NC}"
|
|
fi
|
|
echo
|
|
```
|
|
|
|
### Adjusting Validation Strictness
|
|
|
|
**Strict Mode** (recommended for production):
|
|
```bash
|
|
# Fail on any error
|
|
set -euo pipefail
|
|
```
|
|
|
|
**Lenient Mode** (development only):
|
|
```bash
|
|
# Continue on errors, just report
|
|
set -uo pipefail
|
|
```
|
|
|
|
### Environment-Specific Hooks
|
|
|
|
```bash
|
|
# Check environment
|
|
if [ "${ENV:-}" = "production" ]; then
|
|
# Strict validation for production
|
|
./scripts/validate-stack.sh
|
|
else
|
|
# Lenient for development
|
|
echo "Development environment, skipping some checks"
|
|
fi
|
|
```
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
Git hooks ensure:
|
|
- ✅ No secrets committed
|
|
- ✅ No root-owned files
|
|
- ✅ Full stack validation before commit
|
|
- ✅ Consistent code quality
|
|
- ✅ Automated validation in workflow
|
|
|
|
All scripts are:
|
|
- Executable (`chmod +x`)
|
|
- Well-documented
|
|
- Provide clear error messages
|
|
- Support emergency skip (`--no-verify`)
|
|
- Integrate with CI/CD
|