Coverage for conventional_commits_check.py: 0%
31 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-21 15:08 +0000
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-21 15:08 +0000
1#!/usr/bin/env python3
2import argparse
3import re
4import string
5import sys
8RED = "\033[31m"
10COMMIT_TYPES = {
11 'feat': r'^feat(\(.+\))?:',
12 'fix': r'^fix(\(.+\))?:',
13 'docs': r'^docs(\(.+\))?:',
14 'style': r'^style(\(.+\))?:',
15 'refactor': r'^refactor(\(.+\))?:',
16 'perf': r'^perf(\(.+\))?:',
17 'test': r'^test(\(.+\))?:',
18 'build': r'^build(\(.+\))?:',
19 'ci': r'^ci(\(.+\))?:',
20 'chore': r'^chore(\(.+\))?:',
21 'revert': '^revert: ',
22}
24EMOJIS = {
25 'feat': '✨',
26 'fix': '🐛',
27 'docs': '📚',
28 'style': '💅',
29 'refactor': '🧹',
30 'perf': '🚀',
31 'test': '🧪',
32 'build': '🏗️',
33 'ci': '👷',
34 'chore': '♻️',
35 'revert': '⏪',
36 'merge': '🔀',
37}
40def main():
41 parser = argparse.ArgumentParser()
42 parser.add_argument('commit_message_file')
43 args = parser.parse_args()
45 with open(args.commit_message_file) as file:
46 commit_message = file.read()
48 commit_message = commit_message.strip(string.whitespace + ''.join(EMOJIS.values()))
50 commit_type = None
51 for commit, pattern in COMMIT_TYPES.items():
52 if re.match(pattern, commit_message):
53 commit_type = commit
54 break
56 if not commit_type:
57 print(
58 f'{RED}Commit message does not follow Conventional Commits rules.\n' \
59 f'It must begin with : {", ".join(COMMIT_TYPES.keys())}'
60 )
61 sys.exit(1)
63 emoji = EMOJIS.get(commit_type)
65 if emoji:
66 new_commit_message = f'{emoji} {commit_message}'
67 with open(args.commit_message_file, 'w') as file:
68 file.write(new_commit_message)
70 print('Commit message follows Conventional Commits rules and has been updated with an emoji.')
71 sys.exit(0)
74if __name__ == '__main__':
75 main()