|
| 1 | +#!/usr/bin/env sh |
1 | 2 |
|
| 3 | +# Conventional Commits validator |
| 4 | +# Spec: https://www.conventionalcommits.org/en/v1.0.0/ |
| 5 | +# Format: <type>(<scope>)?(!)?: <description> |
| 6 | +# Types from @commitlint/config-conventional |
2 | 7 |
|
3 | | -# Conventional commit message format |
4 | | -# Format: <type>(<scope>): <description> |
5 | | -# Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert, merge |
6 | | -# Also allows Git's standard merge commit format: "Merge branch '...' of ... into ..." |
7 | | - |
8 | | -# Regex for conventional commits |
9 | | -conventional_regex='^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert|merge)(\(.+\))?: .{1,50}' |
10 | | - |
11 | | -# Regex for Git merge commits |
12 | | -merge_regex='^Merge branch .* of .* into .*' |
13 | | -merge_regex='^Merge branch .* of .*' |
14 | | - |
15 | | -# Combined regex - either conventional or merge format |
16 | | -commit_regex="($conventional_regex|$merge_regex)" |
17 | | - |
18 | | -if ! grep -qE "$commit_regex" "$1"; then |
19 | | - echo "❌ Invalid commit message format." |
20 | | - echo "✅ Please use either:" |
21 | | - echo " 1. Conventional commit format: <type>(<scope>): <description>" |
22 | | - echo " 2. Git's standard merge format: Merge branch '...' of ... into ..." |
23 | | - echo "" |
24 | | - echo "📝 Examples:" |
25 | | - echo " feat: add new wallet connection feature" |
26 | | - echo " fix(wallet): resolve persistence issue" |
27 | | - echo " docs: update README with setup instructions" |
28 | | - echo " style: format code with prettier" |
29 | | - echo " refactor(components): improve wallet button" |
30 | | - echo " Merge branch 'main' of https://github.com/user/repo into feature/branch" |
31 | | - echo "" |
32 | | - echo "🔧 Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert, merge" |
33 | | - exit 1 |
| 8 | +commit_msg_file="$1" |
| 9 | +first_line=$(head -n1 "$commit_msg_file") |
| 10 | + |
| 11 | +# Ignore comment lines and empty messages |
| 12 | +if [ -z "$first_line" ] || echo "$first_line" | grep -qE '^#'; then |
| 13 | + exit 0 |
| 14 | +fi |
| 15 | + |
| 16 | +# Conventional commits regex (types from @commitlint/config-conventional) |
| 17 | +conventional_regex='^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z0-9._\-]+\))?!?: .+' |
| 18 | + |
| 19 | +# Git auto-generated merge/revert commits |
| 20 | +merge_regex='^Merge (branch|remote-tracking branch|tag|pull request) ' |
| 21 | +revert_regex='^Revert ".+"' |
| 22 | + |
| 23 | +# Fixup/squash commits (used with `git commit --fixup` / `--squash`, resolved on rebase) |
| 24 | +fixup_regex='^(fixup|squash)! ' |
| 25 | + |
| 26 | +if echo "$first_line" | grep -qE "$conventional_regex"; then |
| 27 | + exit 0 |
| 28 | +fi |
| 29 | + |
| 30 | +if echo "$first_line" | grep -qE "$merge_regex"; then |
| 31 | + exit 0 |
| 32 | +fi |
| 33 | + |
| 34 | +if echo "$first_line" | grep -qE "$revert_regex"; then |
| 35 | + exit 0 |
| 36 | +fi |
| 37 | + |
| 38 | +if echo "$first_line" | grep -qE "$fixup_regex"; then |
| 39 | + exit 0 |
34 | 40 | fi |
35 | 41 |
|
36 | | -echo "✅ Commit message format is valid!" |
| 42 | +echo "❌ Invalid commit message format." |
| 43 | +echo "" |
| 44 | +echo "Expected Conventional Commits format:" |
| 45 | +echo " <type>(<scope>)?: <description>" |
| 46 | +echo "" |
| 47 | +echo "Allowed types:" |
| 48 | +echo " build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test" |
| 49 | +echo "" |
| 50 | +echo "Examples:" |
| 51 | +echo " feat: add new wallet connection feature" |
| 52 | +echo " fix(wallet): resolve persistence issue" |
| 53 | +echo " chore(deps): bump smart-account-kit to 0.4.2" |
| 54 | +echo " refactor(components)!: drop legacy wallet button props" |
| 55 | +echo "" |
| 56 | +echo "Tip: for dependency bumps use 'chore(deps):' or 'build(deps):'." |
| 57 | +exit 1 |
0 commit comments