Initial commit
This commit is contained in:
96
hooks/scripts/validate-branch-name.py
Executable file
96
hooks/scripts/validate-branch-name.py
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import sys
|
||||
import re
|
||||
|
||||
try:
|
||||
input_data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Invalid JSON input: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
tool_name = input_data.get("tool_name", "")
|
||||
tool_input = input_data.get("tool_input", {})
|
||||
command = tool_input.get("command", "")
|
||||
|
||||
# Only validate git checkout -b commands
|
||||
if tool_name != "Bash" or "git checkout -b" not in command:
|
||||
sys.exit(0)
|
||||
|
||||
# Extract branch name
|
||||
match = re.search(r'git checkout -b\s+([^\s]+)', command)
|
||||
if not match:
|
||||
sys.exit(0)
|
||||
|
||||
branch_name = match.group(1)
|
||||
|
||||
# Allow main and develop branches
|
||||
if branch_name in ["main", "develop"]:
|
||||
sys.exit(0)
|
||||
|
||||
# Validate Git Flow naming convention
|
||||
if not re.match(r'^(feature|release|hotfix)/', branch_name):
|
||||
reason = f"""❌ Invalid Git Flow branch name: {branch_name}
|
||||
|
||||
Git Flow branches must follow these patterns:
|
||||
• feature/<descriptive-name>
|
||||
• release/v<MAJOR>.<MINOR>.<PATCH>
|
||||
• hotfix/<descriptive-name>
|
||||
|
||||
Examples:
|
||||
✅ feature/user-authentication
|
||||
✅ release/v1.2.0
|
||||
✅ hotfix/critical-security-fix
|
||||
|
||||
Invalid:
|
||||
❌ {branch_name} (missing Git Flow prefix)
|
||||
❌ feat/something (use 'feature/' not 'feat/')
|
||||
❌ fix/bug (use 'hotfix/' not 'fix/')
|
||||
|
||||
💡 Use Git Flow commands instead:
|
||||
/feature <name> - Create feature branch
|
||||
/release <version> - Create release branch
|
||||
/hotfix <name> - Create hotfix branch"""
|
||||
|
||||
output = {
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "deny",
|
||||
"permissionDecisionReason": reason
|
||||
}
|
||||
}
|
||||
print(json.dumps(output))
|
||||
sys.exit(0)
|
||||
|
||||
# Validate release version format
|
||||
if branch_name.startswith("release/"):
|
||||
if not re.match(r'^release/v\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$', branch_name):
|
||||
reason = f"""❌ Invalid release version: {branch_name}
|
||||
|
||||
Release branches must follow semantic versioning:
|
||||
release/vMAJOR.MINOR.PATCH[-prerelease]
|
||||
|
||||
Valid examples:
|
||||
✅ release/v1.0.0
|
||||
✅ release/v2.1.3
|
||||
✅ release/v1.0.0-beta.1
|
||||
|
||||
Invalid:
|
||||
❌ release/1.0.0 (missing 'v' prefix)
|
||||
❌ release/v1.0 (incomplete version)
|
||||
❌ {branch_name}
|
||||
|
||||
💡 Use: /release v1.2.0"""
|
||||
|
||||
output = {
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "deny",
|
||||
"permissionDecisionReason": reason
|
||||
}
|
||||
}
|
||||
print(json.dumps(output))
|
||||
sys.exit(0)
|
||||
|
||||
# Allow the command
|
||||
sys.exit(0)
|
||||
Reference in New Issue
Block a user