Browse Source
- 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.mdpull/153/head
1 changed files with 381 additions and 0 deletions
@ -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…
Reference in new issue