Browse Source

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
pull/153/head
Matthew Raymer 15 hours ago
parent
commit
4829582584
  1. 381
      doc/husky-conditional-activation.md

381
doc/husky-conditional-activation.md

@ -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
Loading…
Cancel
Save