forked from trent_larson/crowd-funder-for-time-pwa
feat(git): implement debug code prevention system with deliberate installation
Implements comprehensive pre-commit hook system to prevent debug code from reaching protected branches while maintaining developer choice. - Hooks stored in scripts/git-hooks/ (not in .git tree) - Deliberate installation required - no forced behavior - Automated installation script for team members - Comprehensive testing - Branch-aware execution (protected vs feature branches) - Configurable patterns and protected branch list Philosophy: Each developer chooses whether to use the hook, ensuring team flexibility while providing powerful debug code prevention tools.
This commit is contained in:
@@ -18,15 +18,17 @@ A pre-commit hook that automatically detects and prevents debug code from reachi
|
||||
./scripts/install-debug-hook.sh
|
||||
```
|
||||
|
||||
This automatically installs, updates, and verifies the hook in your current repository.
|
||||
This automatically installs, updates, and verifies the hook in your current
|
||||
repository. **Note**: Hooks are not automatically installed - you must run this
|
||||
script deliberately to enable debug code checking.
|
||||
|
||||
## 🔧 Manual Installation
|
||||
|
||||
**Copy files manually:**
|
||||
|
||||
```bash
|
||||
cp .git/hooks/pre-commit /path/to/your/repo/.git/hooks/
|
||||
cp .git/hooks/debug-checker.config /path/to/your/repo/.git/hooks/
|
||||
cp scripts/git-hooks/pre-commit /path/to/your/repo/.git/hooks/
|
||||
cp scripts/git-hooks/debug-checker.config /path/to/your/repo/.git/hooks/
|
||||
chmod +x /path/to/your/repo/.git/hooks/pre-commit
|
||||
```
|
||||
|
||||
@@ -36,12 +38,27 @@ chmod +x /path/to/your/repo/.git/hooks/pre-commit
|
||||
- **`debug-checker.config`** - Configuration file
|
||||
- **`README.md`** - Documentation and troubleshooting
|
||||
|
||||
**Note**: Hooks are stored in `scripts/git-hooks/` and must be deliberately
|
||||
installed by each developer. They are not automatically active.
|
||||
|
||||
## 🎯 How It Works
|
||||
|
||||
1. **Branch Detection**: Only runs on protected branches
|
||||
2. **File Filtering**: Automatically skips tests, scripts, and documentation
|
||||
3. **Pattern Matching**: Detects debug code using regex patterns
|
||||
4. **Commit Prevention**: Blocks commits containing debug code
|
||||
1. **Deliberate Installation**: Hooks must be explicitly installed by each
|
||||
developer
|
||||
2. **Branch Detection**: Only runs on protected branches
|
||||
3. **File Filtering**: Automatically skips tests, scripts, and documentation
|
||||
4. **Pattern Matching**: Detects debug code using regex patterns
|
||||
5. **Commit Prevention**: Blocks commits containing debug code
|
||||
|
||||
## 🔒 Installation Philosophy
|
||||
|
||||
**Why deliberate installation?**
|
||||
|
||||
- **Developer choice**: Each developer decides whether to use the hook
|
||||
- **No forced behavior**: Hooks don't interfere with existing workflows
|
||||
- **Local control**: Hooks are installed locally, not globally
|
||||
- **Easy removal**: Can be uninstalled at any time
|
||||
- **Team flexibility**: Some developers may prefer different tools
|
||||
|
||||
## 🌿 Branch Behavior
|
||||
|
||||
@@ -145,8 +162,8 @@ A test script is available at `scripts/test-debug-hook.sh` to verify the hook wo
|
||||
|
||||
## 📚 Additional Resources
|
||||
|
||||
- **Hook documentation**: `.git/hooks/README.md`
|
||||
- **Configuration**: `.git/hooks/debug-checker.config`
|
||||
- **Hook documentation**: `scripts/git-hooks/README.md`
|
||||
- **Configuration**: `scripts/git-hooks/debug-checker.config`
|
||||
- **Test script**: `scripts/test-debug-hook.sh`
|
||||
- **Installation script**: `scripts/install-debug-hook.sh`
|
||||
|
||||
|
||||
103
scripts/git-hooks/README.md
Normal file
103
scripts/git-hooks/README.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# TimeSafari Git Hooks
|
||||
|
||||
This directory contains custom Git hooks for the TimeSafari project.
|
||||
|
||||
## Debug Code Checker Hook
|
||||
|
||||
### Overview
|
||||
The `pre-commit` hook automatically checks for debug code when committing to protected branches (master, main, production, release). This prevents debug statements from accidentally reaching production code.
|
||||
|
||||
### How It Works
|
||||
1. **Branch Detection**: Only runs on protected branches (configurable)
|
||||
2. **File Filtering**: Automatically skips test files, scripts, and documentation
|
||||
3. **Pattern Matching**: Detects common debug patterns using regex
|
||||
4. **Commit Prevention**: Blocks commits containing debug code
|
||||
|
||||
### Protected Branches (Default)
|
||||
- `master`
|
||||
- `main`
|
||||
- `production`
|
||||
- `release`
|
||||
- `stable`
|
||||
|
||||
### Debug Patterns Detected
|
||||
- **Console statements**: `console.log`, `console.debug`, `console.error`
|
||||
- **Template debug**: `Debug:`, `debug:` in Vue templates
|
||||
- **Debug constants**: `DEBUG_`, `debug_` variables
|
||||
- **HTML debug**: `<!-- debug` comments
|
||||
- **Debug attributes**: `debug="true"` attributes
|
||||
- **Vue debug**: `v-if="debug"`, `v-show="debug"`
|
||||
- **Debug TODOs**: `TODO debug`, `FIXME debug`
|
||||
|
||||
### Files Automatically Skipped
|
||||
- Test files: `*.test.js`, `*.spec.ts`, `*.test.vue`
|
||||
- Scripts: `scripts/` directory
|
||||
- Test directories: `test-*` directories
|
||||
- Documentation: `docs/`, `*.md`, `*.txt`
|
||||
- Config files: `*.json`, `*.yml`, `*.yaml`
|
||||
- IDE files: `.cursor/` directory
|
||||
|
||||
### Configuration
|
||||
Edit `.git/hooks/debug-checker.config` to customize:
|
||||
- Protected branches
|
||||
- Debug patterns
|
||||
- Skip patterns
|
||||
- Logging level
|
||||
|
||||
### Testing the Hook
|
||||
Run the test script to verify the hook works:
|
||||
```bash
|
||||
./scripts/test-debug-hook.sh
|
||||
```
|
||||
|
||||
### Manual Testing
|
||||
1. Make changes to a file with debug code
|
||||
2. Stage the file: `git add <filename>`
|
||||
3. Try to commit: `git commit -m 'test'`
|
||||
4. Hook should prevent commit if debug code is found
|
||||
|
||||
### Bypassing the Hook (Emergency)
|
||||
If you absolutely need to commit debug code to a protected branch:
|
||||
```bash
|
||||
git commit --no-verify -m "emergency: debug code needed"
|
||||
```
|
||||
⚠️ **Warning**: This bypasses all pre-commit hooks. Use sparingly and only in emergencies.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### Hook not running
|
||||
- Ensure the hook is executable: `chmod +x .git/hooks/pre-commit`
|
||||
- Check if you're on a protected branch
|
||||
- Verify the hook file exists and has correct permissions
|
||||
|
||||
#### False positives
|
||||
- Add legitimate debug patterns to skip patterns in config
|
||||
- Use proper logging levels (`logger.info`, `logger.debug`) instead of console
|
||||
- Move debug code to feature branches first
|
||||
|
||||
#### Hook too strict
|
||||
- Modify debug patterns in config file
|
||||
- Add more file types to skip patterns
|
||||
- Adjust protected branch list
|
||||
|
||||
### Best Practices
|
||||
1. **Use feature branches** for development with debug code
|
||||
2. **Use proper logging** instead of console statements
|
||||
3. **Test thoroughly** before merging to protected branches
|
||||
4. **Review commits** to ensure no debug code slips through
|
||||
5. **Keep config updated** as project needs change
|
||||
|
||||
### Integration with CI/CD
|
||||
This hook works locally. For CI/CD pipelines, consider:
|
||||
- Running the same checks in your build process
|
||||
- Adding ESLint rules for console statements
|
||||
- Using TypeScript strict mode
|
||||
- Adding debug code detection to PR checks
|
||||
|
||||
### Support
|
||||
If you encounter issues:
|
||||
1. Check the hook output for specific error messages
|
||||
2. Verify your branch is in the protected list
|
||||
3. Review the configuration file
|
||||
4. Test with the provided test script
|
||||
5. Check file permissions and git setup
|
||||
70
scripts/git-hooks/debug-checker.config
Normal file
70
scripts/git-hooks/debug-checker.config
Normal file
@@ -0,0 +1,70 @@
|
||||
# TimeSafari Debug Checker Configuration
|
||||
# Edit this file to customize protected branches and debug patterns
|
||||
|
||||
# Protected branches where debug code checking is enforced
|
||||
# Add or remove branches as needed
|
||||
PROTECTED_BRANCHES=(
|
||||
"master"
|
||||
"main"
|
||||
"production"
|
||||
"release"
|
||||
"stable"
|
||||
)
|
||||
|
||||
# Debug patterns to detect (regex patterns)
|
||||
# Add or remove patterns as needed
|
||||
DEBUG_PATTERNS=(
|
||||
# Console statements
|
||||
"console\."
|
||||
|
||||
# Template debug text
|
||||
"Debug:"
|
||||
"debug:"
|
||||
|
||||
# Debug constants and variables
|
||||
"DEBUG_"
|
||||
"debug_"
|
||||
|
||||
# HTML debug comments
|
||||
"<!-- debug"
|
||||
|
||||
# Debug attributes
|
||||
"debug.*="
|
||||
|
||||
# Vue debug patterns
|
||||
"v-if.*debug"
|
||||
"v-show.*debug"
|
||||
|
||||
# Common debug text
|
||||
"TODO.*debug"
|
||||
"FIXME.*debug"
|
||||
|
||||
# Debug imports (uncomment if you want to catch these)
|
||||
# "import.*debug"
|
||||
# "require.*debug"
|
||||
)
|
||||
|
||||
# Files and directories to skip during checking
|
||||
# Add patterns to exclude from debug checking
|
||||
SKIP_PATTERNS=(
|
||||
"\.(test|spec)\.(js|ts|vue)$" # Test files (must have .test. or .spec.)
|
||||
"^scripts/" # Scripts directory
|
||||
"^test-.*/" # Test directories (must end with /)
|
||||
"^\.git/" # Git directory
|
||||
"^node_modules/" # Dependencies
|
||||
"^docs/" # Documentation
|
||||
"^\.cursor/" # Cursor IDE files
|
||||
"\.md$" # Markdown files
|
||||
"\.txt$" # Text files
|
||||
"\.json$" # JSON config files
|
||||
"\.yml$" # YAML config files
|
||||
"\.yaml$" # YAML config files
|
||||
)
|
||||
|
||||
# Logging level (debug, info, warn, error)
|
||||
LOG_LEVEL="info"
|
||||
|
||||
# Exit codes
|
||||
EXIT_SUCCESS=0
|
||||
EXIT_DEBUG_FOUND=1
|
||||
EXIT_ERROR=2
|
||||
213
scripts/git-hooks/pre-commit
Executable file
213
scripts/git-hooks/pre-commit
Executable file
@@ -0,0 +1,213 @@
|
||||
#!/bin/bash
|
||||
|
||||
# TimeSafari Pre-commit Hook - Debug Code Checker
|
||||
# Only runs on master or specified branches to catch debug code before it reaches production
|
||||
|
||||
# Hook directory
|
||||
HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CONFIG_FILE="$HOOK_DIR/debug-checker.config"
|
||||
|
||||
# Default configuration (fallback if config file is missing)
|
||||
DEFAULT_PROTECTED_BRANCHES=("master" "main" "production" "release")
|
||||
DEFAULT_DEBUG_PATTERNS=(
|
||||
"console\."
|
||||
"Debug:"
|
||||
"debug:"
|
||||
"DEBUG_"
|
||||
"debug_"
|
||||
"<!-- debug"
|
||||
"debug.*="
|
||||
)
|
||||
|
||||
# Load configuration from file if it exists
|
||||
load_config() {
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
# Source the config file to load variables
|
||||
# We'll use a safer approach by reading and parsing
|
||||
PROTECTED_BRANCHES=()
|
||||
DEBUG_PATTERNS=()
|
||||
SKIP_PATTERNS=()
|
||||
|
||||
# Read protected branches
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^PROTECTED_BRANCHES=\( ]]; then
|
||||
# Start reading array
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^\)$ ]]; then
|
||||
break
|
||||
fi
|
||||
if [[ "$line" =~ \"([^\"]+)\" ]]; then
|
||||
PROTECTED_BRANCHES+=("${BASH_REMATCH[1]}")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done < "$CONFIG_FILE"
|
||||
|
||||
# Read debug patterns
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^DEBUG_PATTERNS=\( ]]; then
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^\)$ ]]; then
|
||||
break
|
||||
fi
|
||||
if [[ "$line" =~ \"([^\"]+)\" ]]; then
|
||||
DEBUG_PATTERNS+=("${BASH_REMATCH[1]}")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done < "$CONFIG_FILE"
|
||||
|
||||
# Read skip patterns
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^SKIP_PATTERNS=\( ]]; then
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^\)$ ]]; then
|
||||
break
|
||||
fi
|
||||
if [[ "$line" =~ \"([^\"]+)\" ]]; then
|
||||
SKIP_PATTERNS+=("${BASH_REMATCH[1]}")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done < "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Use defaults if config loading failed
|
||||
if [[ ${#PROTECTED_BRANCHES[@]} -eq 0 ]]; then
|
||||
PROTECTED_BRANCHES=("${DEFAULT_PROTECTED_BRANCHES[@]}")
|
||||
fi
|
||||
|
||||
if [[ ${#DEBUG_PATTERNS[@]} -eq 0 ]]; then
|
||||
DEBUG_PATTERNS=("${DEFAULT_DEBUG_PATTERNS[@]}")
|
||||
fi
|
||||
|
||||
if [[ ${#SKIP_PATTERNS[@]} -eq 0 ]]; then
|
||||
SKIP_PATTERNS=("${DEFAULT_SKIP_PATTERNS[@]}")
|
||||
fi
|
||||
|
||||
|
||||
}
|
||||
|
||||
# Check if current branch is protected
|
||||
is_protected_branch() {
|
||||
local branch="$1"
|
||||
for protected in "${PROTECTED_BRANCHES[@]}"; do
|
||||
if [[ "$branch" == "$protected" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if file should be skipped
|
||||
should_skip_file() {
|
||||
local file="$1"
|
||||
for pattern in "${SKIP_PATTERNS[@]}"; do
|
||||
if [[ "$file" =~ $pattern ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
# Load configuration
|
||||
load_config
|
||||
|
||||
# Get current branch name
|
||||
CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null)
|
||||
|
||||
if [[ -z "$CURRENT_BRANCH" ]]; then
|
||||
echo "⚠️ Could not determine current branch, skipping debug check"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if we should run the hook
|
||||
if ! is_protected_branch "$CURRENT_BRANCH"; then
|
||||
echo "🔒 Pre-commit hook skipped - not on protected branch ($CURRENT_BRANCH)"
|
||||
echo " Protected branches: ${PROTECTED_BRANCHES[*]}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "🔍 Running debug code check on protected branch: $CURRENT_BRANCH"
|
||||
echo " Using config: $CONFIG_FILE"
|
||||
|
||||
# Get all staged files (modified, added, copied, merged)
|
||||
ALL_STAGED_FILES=$(git diff --cached --name-only)
|
||||
|
||||
|
||||
|
||||
if [ -z "$ALL_STAGED_FILES" ]; then
|
||||
echo "✅ No staged files to check"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Initialize error tracking
|
||||
ERRORS_FOUND=0
|
||||
ERROR_MESSAGES=()
|
||||
FILES_CHECKED=0
|
||||
|
||||
# Check each staged file for debug patterns
|
||||
for file in $ALL_STAGED_FILES; do
|
||||
# Skip files that should be ignored
|
||||
if should_skip_file "$file"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
FILES_CHECKED=$((FILES_CHECKED + 1))
|
||||
|
||||
# Check for debug patterns in the file
|
||||
for pattern in "${DEBUG_PATTERNS[@]}"; do
|
||||
# For new files, check the file content directly
|
||||
# For modified files, check the staged diff
|
||||
if [[ -f "$file" ]]; then
|
||||
# New file - check content directly
|
||||
if grep -E "$pattern" "$file" > /dev/null; then
|
||||
ERRORS_FOUND=$((ERRORS_FOUND + 1))
|
||||
ERROR_MESSAGES+=("🚨 $file: Found debug pattern '$pattern'")
|
||||
fi
|
||||
else
|
||||
# Modified file - check staged diff
|
||||
if git diff --cached "$file" | grep -E "$pattern" > /dev/null; then
|
||||
ERRORS_FOUND=$((ERRORS_FOUND + 1))
|
||||
ERROR_MESSAGES+=("🚨 $file: Found debug pattern '$pattern'")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Report results
|
||||
if [ $ERRORS_FOUND -gt 0 ]; then
|
||||
echo ""
|
||||
echo "❌ Debug code detected in staged files!"
|
||||
echo " Branch: $CURRENT_BRANCH"
|
||||
echo " Files checked: $FILES_CHECKED"
|
||||
echo " Errors found: $ERRORS_FOUND"
|
||||
echo ""
|
||||
for msg in "${ERROR_MESSAGES[@]}"; do
|
||||
echo " $msg"
|
||||
done
|
||||
echo ""
|
||||
echo "💡 Please remove debug code before committing to $CURRENT_BRANCH"
|
||||
echo " Common debug patterns to check:"
|
||||
echo " - console.log, console.debug, console.error"
|
||||
echo " - Debug: or debug: in templates"
|
||||
echo " - DEBUG_ constants"
|
||||
echo " - HTML comments with debug"
|
||||
echo ""
|
||||
echo " If debug code is intentional, consider:"
|
||||
echo " - Moving to a feature branch first"
|
||||
echo " - Using proper logging levels (logger.info, logger.debug)"
|
||||
echo " - Adding debug code to .gitignore or .debugignore"
|
||||
echo ""
|
||||
echo " Configuration file: $CONFIG_FILE"
|
||||
exit 1
|
||||
else
|
||||
echo "✅ No debug code found in $FILES_CHECKED staged files"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
171
scripts/install-debug-hook.sh
Executable file
171
scripts/install-debug-hook.sh
Executable file
@@ -0,0 +1,171 @@
|
||||
#!/bin/bash
|
||||
|
||||
# TimeSafari Debug Hook Installer
|
||||
# Run this script in any repository to install the debug pre-commit hook
|
||||
|
||||
set -e
|
||||
|
||||
# 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 -e "${BLUE}🔧 TimeSafari Debug Hook Installer${NC}"
|
||||
echo "============================================="
|
||||
|
||||
# Check if we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo -e "${RED}❌ Error: Not in a git repository${NC}"
|
||||
echo "Please run this script from within a git repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get repository root
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
HOOKS_DIR="$REPO_ROOT/.git/hooks"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
echo -e "${BLUE}Repository:${NC} $REPO_ROOT"
|
||||
echo -e "${BLUE}Hooks directory:${NC} $HOOKS_DIR"
|
||||
echo -e "${BLUE}Script directory:${NC} $SCRIPT_DIR"
|
||||
|
||||
# Check if hooks directory exists
|
||||
if [[ ! -d "$HOOKS_DIR" ]]; then
|
||||
echo -e "${RED}❌ Error: Hooks directory not found${NC}"
|
||||
echo "This repository may not be properly initialized"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if we have the hook files in the repository
|
||||
HOOK_SCRIPT="$SCRIPT_DIR/git-hooks/pre-commit"
|
||||
CONFIG_FILE="$SCRIPT_DIR/git-hooks/debug-checker.config"
|
||||
|
||||
if [[ ! -f "$HOOK_SCRIPT" ]]; then
|
||||
echo -e "${RED}❌ Error: Pre-commit hook script not found${NC}"
|
||||
echo "Expected location: $HOOK_SCRIPT"
|
||||
echo "Make sure you're running this from the TimeSafari repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
echo -e "${RED}❌ Error: Debug checker config not found${NC}"
|
||||
echo "Expected location: $CONFIG_FILE"
|
||||
echo "Make sure you're running this from the TimeSafari repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if already installed
|
||||
if [[ -f "$HOOKS_DIR/pre-commit" && -f "$HOOKS_DIR/debug-checker.config" ]]; then
|
||||
echo -e "${YELLOW}⚠️ Debug hook already appears to be installed${NC}"
|
||||
echo -e " Checking if update is needed..."
|
||||
|
||||
# Check if files are different
|
||||
if diff "$HOOK_SCRIPT" "$HOOKS_DIR/pre-commit" > /dev/null 2>&1; then
|
||||
echo -e " ${GREEN}✅${NC} Hook script is up to date"
|
||||
HOOK_UP_TO_DATE=true
|
||||
else
|
||||
echo -e " ${YELLOW}⚠️ Hook script differs - will update${NC}"
|
||||
HOOK_UP_TO_DATE=false
|
||||
fi
|
||||
|
||||
if diff "$CONFIG_FILE" "$HOOKS_DIR/debug-checker.config" > /dev/null 2>&1; then
|
||||
echo -e " ${GREEN}✅${NC} Config file is up to date"
|
||||
CONFIG_UP_TO_DATE=true
|
||||
else
|
||||
echo -e " ${YELLOW}⚠️ Config file differs - will update${NC}"
|
||||
CONFIG_UP_TO_DATE=false
|
||||
fi
|
||||
|
||||
if [[ "$HOOK_UP_TO_DATE" == true && "$CONFIG_UP_TO_DATE" == true ]]; then
|
||||
echo -e "\n${GREEN}✅ Debug hook is already up to date!${NC}"
|
||||
echo -e " No installation needed"
|
||||
else
|
||||
echo -e "\n${BLUE}Updating existing installation...${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "\n${BLUE}Installing debug hook...${NC}"
|
||||
fi
|
||||
|
||||
# Copy/update the hook script if needed
|
||||
if [[ "$HOOK_UP_TO_DATE" != true ]]; then
|
||||
cp "$HOOK_SCRIPT" "$HOOKS_DIR/pre-commit"
|
||||
chmod +x "$HOOKS_DIR/pre-commit"
|
||||
echo -e " ${GREEN}✅${NC} Pre-commit hook installed/updated"
|
||||
fi
|
||||
|
||||
# Copy/update the config file if needed
|
||||
if [[ "$CONFIG_UP_TO_DATE" != true ]]; then
|
||||
cp "$CONFIG_FILE" "$HOOKS_DIR/debug-checker.config"
|
||||
echo -e " ${GREEN}✅${NC} Configuration file installed/updated"
|
||||
fi
|
||||
|
||||
# Copy/update the README if needed
|
||||
README_FILE="$SCRIPT_DIR/git-hooks/README.md"
|
||||
if [[ -f "$README_FILE" ]]; then
|
||||
if [[ ! -f "$HOOKS_DIR/README.md" ]] || ! diff "$README_FILE" "$HOOKS_DIR/README.md" > /dev/null 2>&1; then
|
||||
cp "$README_FILE" "$HOOKS_DIR/README.md"
|
||||
echo -e " ${GREEN}✅${NC} Documentation installed/updated"
|
||||
else
|
||||
echo -e " ${GREEN}✅${NC} Documentation is up to date"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "\n${GREEN}🎉 Debug hook installation complete!${NC}"
|
||||
|
||||
# Test the installation
|
||||
echo -e "\n${BLUE}Testing installation...${NC}"
|
||||
if [[ -x "$HOOKS_DIR/pre-commit" ]]; then
|
||||
echo -e " ${GREEN}✅${NC} Hook is executable"
|
||||
else
|
||||
echo -e " ${RED}❌${NC} Hook is not executable"
|
||||
fi
|
||||
|
||||
if [[ -f "$HOOKS_DIR/debug-checker.config" ]]; then
|
||||
echo -e " ${GREEN}✅${NC} Config file exists"
|
||||
else
|
||||
echo -e " ${RED}❌${NC} Config file missing"
|
||||
fi
|
||||
|
||||
# Show current branch status
|
||||
CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "detached")
|
||||
echo -e "\n${BLUE}Current branch:${NC} $CURRENT_BRANCH"
|
||||
|
||||
# Check if this is a protected branch
|
||||
PROTECTED_BRANCHES=("master" "main" "production" "release" "stable")
|
||||
IS_PROTECTED=false
|
||||
|
||||
for branch in "${PROTECTED_BRANCHES[@]}"; do
|
||||
if [[ "$CURRENT_BRANCH" == "$branch" ]]; then
|
||||
IS_PROTECTED=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$IS_PROTECTED" == true ]]; then
|
||||
echo -e "${YELLOW}⚠️ You're on a protected branch ($CURRENT_BRANCH)${NC}"
|
||||
echo -e " The debug hook will now run on all commits to this branch"
|
||||
echo -e " Consider switching to a feature branch for development"
|
||||
else
|
||||
echo -e "${GREEN}✅ You're on a feature branch ($CURRENT_BRANCH)${NC}"
|
||||
echo -e " The debug hook will be skipped on this branch"
|
||||
echo -e " You can develop with debug code freely"
|
||||
fi
|
||||
|
||||
echo -e "\n${BLUE}Next steps:${NC}"
|
||||
echo "1. The hook will now run automatically on protected branches"
|
||||
echo "2. Test it by trying to commit a file with debug code"
|
||||
echo "3. Use feature branches for development with debug code"
|
||||
echo "4. Check the README.md in .git/hooks/ for more information"
|
||||
|
||||
echo -e "\n${BLUE}To test the hook:${NC}"
|
||||
echo "1. Create a test file with debug code (e.g., console.log('test'))"
|
||||
echo "2. Stage it: git add <filename>"
|
||||
echo "3. Try to commit: git commit -m 'test'"
|
||||
echo "4. The hook should prevent the commit if debug code is found"
|
||||
|
||||
echo -e "\n${BLUE}To uninstall:${NC}"
|
||||
echo "rm $HOOKS_DIR/pre-commit"
|
||||
echo "rm $HOOKS_DIR/debug-checker.config"
|
||||
echo "rm $HOOKS_DIR/README.md"
|
||||
117
scripts/test-debug-hook.sh
Executable file
117
scripts/test-debug-hook.sh
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test script for the debug pre-commit hook
|
||||
# This script helps verify that the hook is working correctly
|
||||
|
||||
set -e
|
||||
|
||||
echo "🧪 Testing TimeSafari Debug Pre-commit Hook"
|
||||
echo "============================================="
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Test directory
|
||||
TEST_DIR="$(mktemp -d)"
|
||||
echo -e "${BLUE}Created test directory: $TEST_DIR${NC}"
|
||||
|
||||
# Function to cleanup
|
||||
cleanup() {
|
||||
echo -e "${YELLOW}Cleaning up test directory...${NC}"
|
||||
rm -rf "$TEST_DIR"
|
||||
}
|
||||
|
||||
# Set trap to cleanup on exit
|
||||
trap cleanup EXIT
|
||||
|
||||
# Function to run test
|
||||
run_test() {
|
||||
local test_name="$1"
|
||||
local test_file="$2"
|
||||
local expected_exit="$3"
|
||||
|
||||
echo -e "\n${BLUE}Running test: $test_name${NC}"
|
||||
|
||||
# Create test file
|
||||
echo "$test_file" > "$TEST_DIR/test.vue"
|
||||
|
||||
# Stage the file
|
||||
cd "$TEST_DIR"
|
||||
git init > /dev/null 2>&1
|
||||
git add test.vue > /dev/null 2>&1
|
||||
|
||||
# Run the hook
|
||||
if bash ../../.git/hooks/pre-commit > hook_output.txt 2>&1; then
|
||||
exit_code=0
|
||||
else
|
||||
exit_code=$?
|
||||
fi
|
||||
|
||||
# Check result
|
||||
if [[ $exit_code -eq $expected_exit ]]; then
|
||||
echo -e " ${GREEN}✅ PASS${NC} - Exit code: $exit_code (expected: $expected_exit)"
|
||||
else
|
||||
echo -e " ${RED}❌ FAIL${NC} - Exit code: $exit_code (expected: $expected_exit)"
|
||||
echo -e " ${YELLOW}Hook output:${NC}"
|
||||
cat hook_output.txt
|
||||
fi
|
||||
|
||||
# Cleanup git
|
||||
rm -rf .git
|
||||
rm -f hook_output.txt
|
||||
}
|
||||
|
||||
# Test cases
|
||||
echo -e "\n${BLUE}Test Case 1: Clean file (should pass)${NC}"
|
||||
run_test "Clean file" "// No debug code here" 0
|
||||
|
||||
echo -e "\n${BLUE}Test Case 2: Console statement (should fail)${NC}"
|
||||
run_test "Console statement" "console.log('debug info')" 1
|
||||
|
||||
echo -e "\n${BLUE}Test Case 3: Debug template (should fail)${NC}"
|
||||
run_test "Debug template" "Debug: {{ isMapReady ? 'Map Ready' : 'Map Loading' }}" 1
|
||||
|
||||
echo -e "\n${BLUE}Test Case 4: Debug constant (should fail)${NC}"
|
||||
run_test "Debug constant" "const DEBUG_MODE = true" 1
|
||||
|
||||
echo -e "\n${BLUE}Test Case 5: Mixed content (should fail)${NC}"
|
||||
run_test "Mixed content" "// Some normal code\nconsole.debug('test')\n// More normal code" 1
|
||||
|
||||
echo -e "\n${BLUE}Test Case 6: HTML debug comment (should fail)${NC}"
|
||||
run_test "HTML debug comment" "<!-- debug: this is debug info -->" 1
|
||||
|
||||
echo -e "\n${BLUE}Test Case 7: Debug attribute (should fail)${NC}"
|
||||
run_test "Debug attribute" "<div debug='true'>content</div>" 1
|
||||
|
||||
echo -e "\n${BLUE}Test Case 8: Test file (should be skipped)${NC}"
|
||||
run_test "Test file" "console.log('this should be skipped')" 0
|
||||
|
||||
# Test branch detection
|
||||
echo -e "\n${BLUE}Testing branch detection...${NC}"
|
||||
cd "$TEST_DIR"
|
||||
git init > /dev/null 2>&1
|
||||
git checkout -b feature-branch > /dev/null 2>&1
|
||||
echo "console.log('debug')" > test.vue
|
||||
git add test.vue > /dev/null 2>&1
|
||||
|
||||
if bash ../../.git/hooks/pre-commit > hook_output.txt 2>&1; then
|
||||
echo -e " ${GREEN}✅ PASS${NC} - Hook skipped on feature branch"
|
||||
else
|
||||
echo -e " ${RED}❌ FAIL${NC} - Hook should have been skipped on feature branch"
|
||||
echo -e " ${YELLOW}Hook output:${NC}"
|
||||
cat hook_output.txt
|
||||
fi
|
||||
|
||||
rm -rf .git
|
||||
rm -f hook_output.txt
|
||||
|
||||
echo -e "\n${GREEN}🎉 All tests completed!${NC}"
|
||||
echo -e "\n${BLUE}To test manually:${NC}"
|
||||
echo "1. Make changes to a file with debug code"
|
||||
echo "2. Stage the file: git add <filename>"
|
||||
echo "3. Try to commit: git commit -m 'test'"
|
||||
echo "4. The hook should prevent the commit if debug code is found"
|
||||
Reference in New Issue
Block a user