#!/bin/sh # Commit message validation # Enforces conventional commit format: type(scope)!?: description # # Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert # Scope allows: letters, numbers, hyphens, underscores, slashes, dots # Optional ! for breaking changes # Examples: # feat(tasks): add drag and drop support # fix(terminal): resolve scroll position issue # feat!: breaking change without scope # feat(api)!: breaking change with scope # docs: update README with setup instructions # chore: update dependencies commit_msg_file=$1 commit_msg=$(cat "$commit_msg_file") # Regex for conventional commits # Format: type(optional-scope)!?: description # Scope allows: letters, numbers, hyphens, underscores, slashes, dots (consistent with GitHub workflow) # Optional ! for breaking changes: feat!: or feat(scope)!: pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-zA-Z0-9_/.-]+\))?!?: .{1,100}$" # Allow merge commits if echo "$commit_msg" | grep -qE "^Merge "; then exit 0 fi # Allow revert commits if echo "$commit_msg" | grep -qE "^Revert "; then exit 0 fi # Check first line against pattern first_line=$(echo "$commit_msg" | head -n 1) if ! echo "$first_line" | grep -qE "$pattern"; then echo "" echo "ERROR: Invalid commit message format!" echo "" echo "Your message: $first_line" echo "" echo "Expected format: type(scope)!?: description" echo "" echo "Valid types:" echo " feat - A new feature" echo " fix - A bug fix" echo " docs - Documentation changes" echo " style - Code style changes (formatting, semicolons, etc.)" echo " refactor - Code refactoring (no feature/fix)" echo " perf - Performance improvements" echo " test - Adding or updating tests" echo " build - Build system or dependencies" echo " ci - CI/CD configuration" echo " chore - Other changes (maintenance)" echo " revert - Reverting a previous commit" echo "" echo "Examples:" echo " feat(tasks): add drag and drop support" echo " fix(terminal): resolve scroll position issue" echo " feat!: breaking change without scope" echo " feat(api)!: breaking change with scope" echo " docs: update README" echo " chore: update dependencies" echo "" exit 1 fi # Check description length (max 100 chars for first line) if [ ${#first_line} -gt 100 ]; then echo "" echo "ERROR: Commit message first line is too long!" echo "Maximum: 100 characters" echo "Current: ${#first_line} characters" echo "" exit 1 fi exit 0