docs(git-hooks): add conditional Husky activation system documentation
- Documents the conditional Husky activation system for git hooks - Explains how hooks are committed but not automatically activated - Provides user workflows for enabling/disabling hooks - Includes troubleshooting guide and best practices - Covers three activation methods: environment variable, local file, global config - Supports team standards without forcing compliance System: Git hooks with optional activation Location: doc/husky-conditional-activation.md
This commit is contained in:
381
doc/husky-conditional-activation.md
Normal file
381
doc/husky-conditional-activation.md
Normal file
@@ -0,0 +1,381 @@
|
||||
# Husky Conditional Activation System
|
||||
|
||||
**Author**: Matthew Raymer
|
||||
**Date**: 2025-08-21T09:40Z
|
||||
**Status**: 🎯 **ACTIVE** - Git hooks with optional activation
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the **conditional Husky activation system** implemented
|
||||
in the TimeSafari project. The system provides standardized git hooks that are
|
||||
committed to version control but only activate when explicitly enabled by
|
||||
individual developers.
|
||||
|
||||
## Problem Statement
|
||||
|
||||
Traditional Husky implementations face several challenges:
|
||||
|
||||
1. **Automatic activation** on all systems can be disruptive
|
||||
2. **Different environments** may have different requirements
|
||||
3. **Team preferences** vary regarding git hook enforcement
|
||||
4. **CI/CD systems** may not need or want git hooks
|
||||
5. **New developers** may be surprised by unexpected hook behavior
|
||||
|
||||
## Solution: Conditional Activation
|
||||
|
||||
The conditional activation system solves these problems by:
|
||||
|
||||
- **Committing hooks to git** for consistency and version control
|
||||
- **Making hooks optional** by default
|
||||
- **Providing multiple activation methods** for flexibility
|
||||
- **Ensuring hooks exit gracefully** when disabled
|
||||
- **Maintaining team standards** without forcing compliance
|
||||
|
||||
## System Architecture
|
||||
|
||||
### **Core Components**
|
||||
|
||||
```
|
||||
.husky/
|
||||
├── _/husky.sh # Conditional activation logic
|
||||
├── pre-commit # Pre-commit hook (linting)
|
||||
├── commit-msg # Commit message validation
|
||||
└── README.md # User activation instructions
|
||||
```
|
||||
|
||||
### **Activation Methods**
|
||||
|
||||
#### **Method 1: Environment Variable (Session Only)**
|
||||
|
||||
```bash
|
||||
export HUSKY_ENABLED=1
|
||||
```
|
||||
|
||||
- **Scope**: Current terminal session only
|
||||
- **Use case**: Temporary activation for testing
|
||||
- **Reset**: `unset HUSKY_ENABLED`
|
||||
|
||||
#### **Method 2: Local File (Persistent)**
|
||||
|
||||
```bash
|
||||
touch .husky-enabled
|
||||
```
|
||||
|
||||
- **Scope**: Current repository, persistent
|
||||
- **Use case**: Long-term activation for development
|
||||
- **Reset**: `rm .husky-enabled`
|
||||
|
||||
#### **Method 3: Global Git Configuration**
|
||||
|
||||
```bash
|
||||
git config --global husky.enabled true
|
||||
```
|
||||
|
||||
- **Scope**: All repositories for current user
|
||||
- **Use case**: Developer preference across projects
|
||||
- **Reset**: `git config --global --unset husky.enabled`
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### **Conditional Activation Logic**
|
||||
|
||||
The core logic in `.husky/_/husky.sh`:
|
||||
|
||||
```bash
|
||||
# Check if Husky is enabled for this user
|
||||
if [ "$HUSKY_ENABLED" != "1" ] && [ ! -f .husky-enabled ]; then
|
||||
echo "Husky is not enabled. To enable:"
|
||||
echo " export HUSKY_ENABLED=1"
|
||||
echo " or create .husky-enabled file"
|
||||
exit 0 # Graceful exit, not an error
|
||||
fi
|
||||
```
|
||||
|
||||
### **Hook Behavior**
|
||||
|
||||
When **disabled**:
|
||||
|
||||
- Hooks display helpful activation instructions
|
||||
- Exit with code 0 (success, not error)
|
||||
- No git operations are blocked
|
||||
- No performance impact
|
||||
|
||||
When **enabled**:
|
||||
|
||||
- Hooks run normally with full functionality
|
||||
- Standard Husky behavior applies
|
||||
- Git operations may be blocked if hooks fail
|
||||
|
||||
## Available Hooks
|
||||
|
||||
### **Pre-commit Hook**
|
||||
|
||||
**File**: `.husky/pre-commit`
|
||||
**Purpose**: Code quality enforcement before commits
|
||||
**Action**: Runs `npm run lint-fix`
|
||||
**When**: Before each commit
|
||||
**Failure**: Prevents commit if linting fails
|
||||
|
||||
**Activation Check**:
|
||||
|
||||
```bash
|
||||
if [ "$HUSKY_ENABLED" = "1" ] || [ -f .husky-enabled ]; then
|
||||
echo "Running pre-commit hooks..."
|
||||
npm run lint-fix
|
||||
else
|
||||
echo "Husky pre-commit hook skipped (not enabled)"
|
||||
exit 0
|
||||
fi
|
||||
```
|
||||
|
||||
### **Commit-msg Hook**
|
||||
|
||||
**File**: `.husky/commit-msg`
|
||||
**Purpose**: Commit message format validation
|
||||
**Action**: Runs `npx commitlint --edit "$1"`
|
||||
**When**: After commit message is written
|
||||
**Failure**: Prevents commit if message format is invalid
|
||||
|
||||
**Activation Check**:
|
||||
|
||||
```bash
|
||||
if [ "$HUSKY_ENABLED" = "1" ] || [ -f .husky-enabled ]; then
|
||||
echo "Running commit-msg hooks..."
|
||||
npx commitlint --edit "$1"
|
||||
else
|
||||
echo "Husky commit-msg hook skipped (not enabled)"
|
||||
exit 0
|
||||
fi
|
||||
```
|
||||
|
||||
## User Workflows
|
||||
|
||||
### **New Developer Setup**
|
||||
|
||||
1. **Clone repository**
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd <repository-name>
|
||||
```
|
||||
|
||||
2. **Hooks are present but inactive**
|
||||
- Pre-commit and commit-msg hooks exist
|
||||
- No automatic activation
|
||||
- Git operations work normally
|
||||
|
||||
3. **Optional: Enable hooks**
|
||||
|
||||
```bash
|
||||
# For current session only
|
||||
export HUSKY_ENABLED=1
|
||||
|
||||
# For persistent activation
|
||||
touch .husky-enabled
|
||||
```
|
||||
|
||||
### **Daily Development**
|
||||
|
||||
#### **With Hooks Disabled**
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: add new feature"
|
||||
# Hooks are skipped, commit proceeds normally
|
||||
```
|
||||
|
||||
#### **With Hooks Enabled**
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat: add new feature"
|
||||
# Pre-commit hook runs linting
|
||||
# Commit-msg hook validates message format
|
||||
# Commit only proceeds if all hooks pass
|
||||
```
|
||||
|
||||
### **Troubleshooting**
|
||||
|
||||
#### **Hooks Not Running**
|
||||
|
||||
```bash
|
||||
# Check if hooks are enabled
|
||||
echo $HUSKY_ENABLED
|
||||
ls -la .husky-enabled
|
||||
|
||||
# Enable hooks
|
||||
export HUSKY_ENABLED=1
|
||||
# or
|
||||
touch .husky-enabled
|
||||
```
|
||||
|
||||
#### **Hooks Running Unexpectedly**
|
||||
|
||||
```bash
|
||||
# Disable hooks
|
||||
unset HUSKY_ENABLED
|
||||
rm -f .husky-enabled
|
||||
|
||||
# Check global configuration
|
||||
git config --global --get husky.enabled
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### **`.gitignore` Entry**
|
||||
|
||||
```gitignore
|
||||
# Husky activation file (user-specific)
|
||||
.husky-enabled
|
||||
```
|
||||
|
||||
This ensures that:
|
||||
|
||||
- Hooks are committed to git (team standard)
|
||||
- Activation files are not committed (user preference)
|
||||
- Each developer can control their own activation
|
||||
|
||||
### **Package.json Dependencies**
|
||||
|
||||
```json
|
||||
{
|
||||
"devDependencies": {
|
||||
"husky": "^9.0.11",
|
||||
"@commitlint/cli": "^18.6.1",
|
||||
"@commitlint/config-conventional": "^18.6.2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
### **For Development Teams**
|
||||
|
||||
1. **Consistency**: All developers have the same hook configuration
|
||||
2. **Flexibility**: Individual developers can choose activation
|
||||
3. **Standards**: Team coding standards are enforced when enabled
|
||||
4. **Version Control**: Hook configuration is tracked and versioned
|
||||
5. **Onboarding**: New developers get standardized setup
|
||||
|
||||
### **For Individual Developers**
|
||||
|
||||
1. **Choice**: Control over when hooks are active
|
||||
2. **Performance**: No unnecessary hook execution when disabled
|
||||
3. **Learning**: Gradual adoption of git hook practices
|
||||
4. **Debugging**: Easy to disable hooks for troubleshooting
|
||||
5. **Environment**: Works across different development environments
|
||||
|
||||
### **For CI/CD Systems**
|
||||
|
||||
1. **No Interference**: Hooks don't run in automated environments
|
||||
2. **Consistency**: Same hook logic available if needed
|
||||
3. **Flexibility**: Can enable hooks in specific CI scenarios
|
||||
4. **Reliability**: No unexpected hook failures in automation
|
||||
|
||||
## Best Practices
|
||||
|
||||
### **Team Adoption**
|
||||
|
||||
1. **Start with disabled hooks** for new team members
|
||||
2. **Encourage gradual adoption** of hook activation
|
||||
3. **Document hook benefits** and usage patterns
|
||||
4. **Provide training** on hook configuration
|
||||
5. **Support troubleshooting** when hooks cause issues
|
||||
|
||||
### **Hook Development**
|
||||
|
||||
1. **Keep hooks lightweight** and fast
|
||||
2. **Provide clear error messages** when hooks fail
|
||||
3. **Include helpful activation instructions** in disabled state
|
||||
4. **Test hooks in both enabled and disabled states**
|
||||
5. **Document hook requirements** and dependencies
|
||||
|
||||
### **Configuration Management**
|
||||
|
||||
1. **Commit hook files** to version control
|
||||
2. **Ignore activation files** in .gitignore
|
||||
3. **Document activation methods** clearly
|
||||
4. **Provide examples** for common use cases
|
||||
5. **Maintain backward compatibility** when updating hooks
|
||||
|
||||
## Troubleshooting Guide
|
||||
|
||||
### **Common Issues**
|
||||
|
||||
#### **Hooks Running When Not Expected**
|
||||
|
||||
```bash
|
||||
# Check all activation methods
|
||||
echo "Environment variable: $HUSKY_ENABLED"
|
||||
echo "Local file exists: $([ -f .husky-enabled ] && echo "yes" || echo "no")"
|
||||
echo "Global config: $(git config --global --get husky.enabled)"
|
||||
```
|
||||
|
||||
#### **Hooks Not Running When Expected**
|
||||
|
||||
```bash
|
||||
# Verify hook files exist and are executable
|
||||
ls -la .husky/
|
||||
chmod +x .husky/pre-commit
|
||||
chmod +x .husky/commit-msg
|
||||
```
|
||||
|
||||
#### **Permission Denied Errors**
|
||||
|
||||
```bash
|
||||
# Fix file permissions
|
||||
chmod +x .husky/_/husky.sh
|
||||
chmod +x .husky/pre-commit
|
||||
chmod +x .husky/commit-msg
|
||||
```
|
||||
|
||||
### **Debug Mode**
|
||||
|
||||
Enable debug output to troubleshoot hook issues:
|
||||
|
||||
```bash
|
||||
export HUSKY_DEBUG=1
|
||||
export HUSKY_ENABLED=1
|
||||
git commit -m "test: debug commit"
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### **Planned Improvements**
|
||||
|
||||
1. **Hook Configuration File**: YAML/JSON configuration for hook behavior
|
||||
2. **Selective Hook Activation**: Enable/disable specific hooks individually
|
||||
3. **Hook Performance Metrics**: Track execution time and success rates
|
||||
4. **Integration with IDEs**: IDE-specific activation methods
|
||||
5. **Remote Configuration**: Team-wide hook settings via configuration
|
||||
|
||||
### **Extension Points**
|
||||
|
||||
1. **Custom Hook Scripts**: Easy addition of project-specific hooks
|
||||
2. **Hook Templates**: Reusable hook patterns for common tasks
|
||||
3. **Conditional Logic**: Complex activation rules based on context
|
||||
4. **Notification System**: Hook status reporting and alerts
|
||||
5. **Analytics**: Hook usage and effectiveness tracking
|
||||
|
||||
## Conclusion
|
||||
|
||||
The conditional Husky activation system provides an elegant solution to the
|
||||
challenges of git hook management in team environments. By committing
|
||||
standardized hooks while making activation optional, it balances consistency
|
||||
with flexibility, enabling teams to maintain coding standards without forcing compliance.
|
||||
|
||||
This approach supports gradual adoption, respects individual preferences, and
|
||||
provides a solid foundation for git hook practices that can evolve with team needs
|
||||
and project requirements.
|
||||
|
||||
---
|
||||
|
||||
**Related Documents**:
|
||||
|
||||
- [Git Hooks Best Practices](./git-hooks-best-practices.md)
|
||||
- [Code Quality Standards](./code-quality-standards.md)
|
||||
- [Development Workflow](./development-workflow.md)
|
||||
|
||||
**Maintainer**: Development Team
|
||||
**Review Schedule**: Quarterly
|
||||
**Next Review**: 2025-11-21
|
||||
Reference in New Issue
Block a user